提问人:Janilson 提问时间:6/18/2023 最后编辑:Janilson 更新时间:6/18/2023 访问量:51
如何解决这种可变参数模板歧义
How to solve this variadic template ambiguity
问:
只要注释掉,以下代码就可以编译并正常运行。但是,一旦取消注释,编译就会失败,并出现错误“ 'value' is not a member of 'Arity<int (*)(int, int)>' ” 编译错误,我认为这是由于编译器选择了第一个模板而不是第二个模板。我尝试从第一个模板中删除括号,但问题仍然存在,只是这次出现了“不完整类型”编译错误。someFuncTemplate(func1)
Arity<F>::value
使用时如何强制编译器选择正确的模板?Arity<F>
#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 F>
void someFuncTemplate(F)
{
std::cout << Arity<F>::value;
}
int main()
{
std::cout << Arity<decltype(func1)>::value << '\n';
//someFuncTemplate(func1);
}
答:
4赞
Ted Lyngmo
6/18/2023
#1
您需要为第二种情况添加另一个专业化:
template <typename Ret, typename... Args>
struct Arity<Ret (*)(Args...)> : Arity<Ret(Args...)> {};
// ^^^
您还可以添加
template <typename Ret, typename... Args>
struct Arity<Ret (&)(Args...)> : Arity<Ret(Args...)> {};
为了做出如下所示的函数声明:
template <typename F>
void someFuncTemplate(F&&) {
std::cout << Arity<F>::value;
}
评论
0赞
Janilson
6/18/2023
嗯,这比我想象的要简单。Ret(Args...) 和 Ret(*)(Args...) 有什么区别?
0赞
Ted Lyngmo
6/18/2023
@Janilson 当您将函数作为参数传递给函数而不是像在 中那样对它执行操作时,它就是这种类型。 与F
decltype
main
someFuncTemplate(func1);
someFuncTemplate(&func1);
2赞
Jerry Coffin
6/18/2023
#2
作为为指向函数的指针添加专用化的替代方法,您可以修改为通过引用获取其参数:someFunctTemplate
// preceding unchanged
template <typename F>
void someFuncTemplate(F const &)
//......................^^^^^^^
{
std::cout << Arity<F>::value;
}
int main()
{
someFuncTemplate(func1);
}
评论