如何将可变参数函数模板实例化声明为别名并用作模板参数?
问题分析与解决方案
你的代码中using myFoo = int (foo)<int,int,int>(int,int,int)的写法不符合C++语法,因为foo<int,int,int>是函数模板实例化后的函数实体,而using只能定义类型别名,不能直接把函数实体作为类型。不过确实可以通过正确的方式为函数类型/指针起别名,再用作模板参数,或者直接将函数实体作为非类型模板参数传递。
方法1:用decltype获取函数类型别名
通过decltype获取实例化后foo的函数类型,再将该类型作为模板参数传递,调用时需要使用对应的函数实例:
#include <utility> template <typename... Args> constexpr auto foo(Args&&... args) noexcept { return (args + ...); // 示例实现:可变参数求和 } class X { public: // 获取foo<int,int,int>的函数类型 using myFoo = decltype(foo<int, int, int>); X() { call<myFoo>(); } template <typename FuncType> auto call() { // 函数类型无法直接调用,需使用对应的函数实例 return foo<int, int, int>(1, 2, 3); } };
方法2:使用函数指针类型别名
定义函数指针类型,将实例化后的foo的地址作为模板参数传递:
#include <utility> template <typename... Args> constexpr auto foo(Args&&... args) noexcept { return (args + ...); } class X { public: // 定义foo<int,int,int>对应的函数指针类型 using myFooPtr = decltype(&foo<int, int, int>); X() { // 传递函数指针作为模板参数 call<&foo<int, int, int>>(); } template <myFooPtr FuncPtr> auto call() { return FuncPtr(1, 2, 3); } };
方法3:直接使用非类型模板参数(C++17及以上)
C++17允许将constexpr函数作为非类型模板参数直接传递,无需额外别名,写法更简洁:
#include <utility> template <typename... Args> constexpr auto foo(Args&&... args) noexcept { return (args + ...); } class X { public: X() { // 直接传递实例化后的foo的地址作为非类型模板参数 call<&foo<int, int, int>>(); } // 模板参数为任意可调用的指针/引用(需满足constexpr要求) template <auto FuncPtr> auto call() { return FuncPtr(1, 2, 3); } };
关键注意点
- 函数模板实例化后得到的是具体的函数实体,不能直接用
using将其定义为类型,必须通过decltype获取它的函数类型或函数指针类型。 - 如果你的
foo不是constexpr函数,方法3的非类型模板参数传递可能无法通过编译,此时优先使用方法1或方法2。 - 注意
foo的参数类型:因为你用了转发引用Args&&...,foo<int,int,int>的参数类型是int&&, int&&, int&&,调用时传入1,2,3(右值)是匹配的;如果需要接受左值,可能需要调整实例化方式,比如foo<int&,int&,int&>。
内容的提问来源于stack exchange,提问作者Code4Fun
相关产品推荐
相关产品推荐

