未解决的重载参数的变量函数模板奇怪的错误消息

时间:2016-04-30 18:56:09

标签: c++ variadic-templates

我在意外地将重载函数传递给可变参数函数模板时遇到了一个令人困惑的错误:

template<typename... Args>
void variadic(Args... args) {}

void overloaded() {}
void overloaded(int) {}

int main()
{
    variadic(overloaded);
}

错误:

prog.cpp: In function 'int main()':
prog.cpp:9:24: error: too many arguments to function 'void variadic(Args ...) [with Args = {}]'
     variadic(overloaded);
                    ^
prog.cpp:2:6: note: declared here
 void variadic(Args... args) {}
      ^

如果我用一个普通的函数模板替换可变参数函数模板,我会得到一个更清晰的错误信息:

prog.cpp: In function 'int main()':
prog.cpp:9:25: error: no matching function for call to 'templated(<unresolved overloaded function type>)'
     templated(overloaded);
                         ^
prog.cpp:2:6: note: candidate: template<class Arg> void templated(Arg)  void templated(Arg args) {}
      ^
prog.cpp:2:6: note:   template argument deduction/substitution failed:
prog.cpp:9:25: note:   couldn't deduce template parameter 'Arg'
     templated(overloaded);
                         ^

任何人都可以解释为什么可变参数错误信息不同?我知道为什么会有一个,只是为什么它与正常模板错误不同。

我使用g ++ 5.2.1和C ++ 14。

在此处试试:https://ideone.com/8XZexs

2 个答案:

答案 0 :(得分:1)

最终,为什么错误消息的问题是它的方式并不是一个有趣的问题 - 没有标准来管理错误消息包含的内容。重要的一点是,gcc(和clang)正确地拒绝了代码格式错误并且能够指向违规行。

来自gcc的错误:

main.cpp:9:24: error: too many arguments to function 'void variadic(Args ...) [with Args = {}]'
     variadic(overloaded);
                    ^

和clang:

main.cpp:9:5: error: no matching function for call to 'variadic'
    variadic(overloaded);
    ^~~~~~~~
main.cpp:2:6: note: candidate function not viable: requires 0 arguments, but 1 was provided
void variadic(Args... args) {}
     ^

碰巧有误导性。似乎未能为Args...推导出overloaded(因为无法进行推导),两个编译器都会回退到尝试为Args...实例化一个空参数包并仅报告void variadic() { }的不可行性是variadic(overloaded)的重载。在非变量的情况下,没有这样的回退,并且两个编译器错误都更有用。

这是一个糟糕的错误消息,希望未来的某些编译器版本能够改进它 - 但重要的是理解为什么代码格式不正确(如您所见),而不是特定的错误消息恰好是。

答案 1 :(得分:-1)

您确定要将函数指针传递给variadic函数吗?

如果那是你想要做的,那么你需要明确指定你想要传递的函数的指针。例如(选择overloaded(int)):

void (*fn)(int) = overloaded;
variadic(fn);

或(选择overloaded()

void (*fn)() = overloaded;
variadic(fn);