能否定义类型特性获取模板函数的模板参数类型?
问题:能否定义类型特性获取模板函数的模板参数?
假设有如下模板函数:
template<typename T> auto foobar () { return std::string("why not"); }
是否可以定义一个类型特性来获取该函数的模板参数?若将该特性命名为get_template_parameter,期望能编写如下代码:
template<typename T> auto foobar () { return std::string("why not"); } using type = typename get_template_parameter <decltype(foobar<double>)>::type; static_assert (std::is_same_v<type,double>);
更新说明:为强调模板参数与函数返回值无关,已为foobar函数添加了一个虚拟返回值。
解决方案
直接通过decltype(foobar<double>)得到的函数类型反向获取模板参数T是做不到的——因为实例化后的普通函数类型里,根本不携带任何原模板参数的元信息。不过我们可以通过添加类型标记、包装器这类方式实现需求:
方法1:给函数返回值添加类型嵌套
修改模板函数,让返回值携带模板参数的类型信息:
#include <string> #include <type_traits> template<typename T> struct FoobarTag { using type = T; // 重载转换运算符,保持原函数的返回值行为 operator std::string() const { return "why not"; } }; template<typename T> auto foobar() { return FoobarTag<T>{}; } // 特化类型特性,提取Tag中的模板参数 template<typename F> struct get_template_parameter; template<typename T> struct get_template_parameter<FoobarTag<T>> { using type = T; }; // 适配函数指针类型,先提取返回值类型再处理 template<typename Ret> struct get_template_parameter<Ret(*)()> { using type = typename get_template_parameter<Ret>::type; }; int main() { using type = typename get_template_parameter<decltype(foobar<double>)>::type; static_assert(std::is_same_v<type, double>); }
方法2:利用函数指针的唯一性关联模板参数
如果不想修改原函数,可以借助编译器对不同模板实例函数指针的类型区分来实现:
#include <string> #include <type_traits> template<typename T> auto foobar() { return std::string("why not"); } // 特化类型特性,匹配foobar<T>的函数指针类型 template<typename T> struct get_template_parameter<decltype(&foobar<T>)> { using type = T; }; int main() { using type = typename get_template_parameter<decltype(foobar<double>)>::type; static_assert(std::is_same_v<type, double>); }
注意:这种方法依赖编译器对不同模板实例的函数指针类型的区分,在标准C++中,decltype(&foobar<T>)确实是唯一对应T的类型,因此是可行的。
核心结论
标准C++里,实例化后的函数类型(比如std::string(*)())本身不包含原模板参数的任何信息,所以无法直接反向推导。必须通过额外的标记、关联机制来保存模板参数的元信息,才能实现get_template_parameter的需求。
内容的提问来源于stack exchange,提问作者abcdefg
相关产品推荐
相关产品推荐

