如何解决C++中Arity可变参数模板的匹配歧义问题?
问题分析与解决方法
问题根源
当你把func1传入someFuncTemplate时,模板参数F会被推导为函数指针类型int(*)(int, int),而你定义的Arity特化只匹配函数类型Ret(Args...)(比如int(int, int)),所以编译器会匹配到空的主模板Arity<T>,自然找不到value成员。
解决方法
方法1:添加函数指针类型的特化
直接给Arity增加针对函数指针的特化模板,剥去指针后复用原有的函数类型特化逻辑:
#include <iostream> template <typename T> struct Arity {}; // 匹配函数类型 template <typename Ret, typename... Args> struct Arity<Ret(Args...)> : std::integral_constant<size_t, sizeof...(Args)> {}; // 匹配函数指针类型,剥去指针后重用上面的特化 template <typename Ret, typename... Args> struct Arity<Ret(*)(Args...)> : Arity<Ret(Args...)> {}; int func1(int a, int b) { return a + b; } template <typename F> void someFuncTemplate(F) { std::cout << Arity<F>::value; } int main() { std::cout << Arity<decltype(func1)>::value << '\n'; someFuncTemplate(func1); // 现在可正常编译 }
方法2:在模板函数中转换为函数类型
借助std::remove_pointer_t把函数指针转换成函数类型,再传给Arity:
#include <iostream> #include <type_traits> // 需包含该头文件 template <typename T> struct Arity {}; template <typename Ret, typename... Args> struct Arity<Ret(Args...)> : std::integral_constant<size_t, sizeof...(Args)> {}; int func1(int a, int b) { return a + b; } template <typename F> void someFuncTemplate(F) { // 剥去指针,得到原始函数类型 using FuncType = std::remove_pointer_t<F>; std::cout << Arity<FuncType>::value; } int main() { std::cout << Arity<decltype(func1)>::value << '\n'; someFuncTemplate(func1); }
方法3:让模板参数直接推导为函数类型
修改someFuncTemplate的参数类型,让它接收函数类型的引用,避免函数名退化为指针:
#include <iostream> template <typename T> struct Arity {}; template <typename Ret, typename... Args> struct Arity<Ret(Args...)> : std::integral_constant<size_t, sizeof...(Args)> {}; int func1(int a, int b) { return a + b; } // 参数为函数类型的引用,直接推导出函数类型而非指针 template <typename Ret, typename... Args> void someFuncTemplate(Ret(&)(Args...)) { std::cout << Arity<Ret(Args...)>::value; } int main() { std::cout << Arity<decltype(func1)>::value << '\n'; someFuncTemplate(func1); }
内容的提问来源于stack exchange,提问作者Janilson
相关产品推荐
相关产品推荐

