c++ - 为什么编译器不给出不明确的引用错误?

标签 c++ c++11 templates gcc clang

引用以下代码

#include <iostream>
#include <tuple>
#include <string>
#include <type_traits>

using std::cout;
using std::endl;
using std::string;

template <typename... Args>
void bar(Args&&...) {}

int change(const string&) { return 1; }
double change(int) { return 1.0; }

int main() {
    // bar(1, 2.0, static_cast<int(*)(const string&)>(&change));
    bar(1, 2.0, &change);
    return 0;
}

我知道上面代码中的错误是对 change 函数的引用不明确(这就是注释行起作用的原因),但是为什么编译器会给出这个错误消息?

test.cpp:17:5: error: no matching function for call to 'bar'
    bar(1, 2.0, &change);
    ^~~
test.cpp:11:6: note: candidate function not viable: requires 2 arguments, but 3 were
      provided
void bar(Args&&...) {}
     ^
1 error generated.

这发生在 gcc (>5) 和 clang (Apple LLVM 版本 8.0.0 (clang-800.0.42.1))

我只是好奇为什么两个编译器不只是说引用不明确。我觉得这与模板实例化在 C++ 中的工作方式有关,但我不确定确切的原因。

最佳答案

我认为编译器是对的,尽管它可能很奇怪。模板参数推导规则不同于替换。模板参数包上下文中重载函数解析的歧义并不一定意味着失败。

[temp.deduct.call]/p6 :

When P is a function type, function pointer type, or pointer to member function type:

...

-- If the argument is an overload set (not containing function templates), trial argument deduction is attempted using each of the members of the set. If deduction succeeds for only one of the overload set members, that member is used as the argument value for the deduction. If deduction succeeds for more than one member of the overload set the parameter is treated as a non-deduced context.

所以对于参数包的最后一个参数,我们处于非推导上下文中(不是错误)。

还有 [temp.arg.explicit]/p3 :

... A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments. ...

所以在我看来(尽管最后一点没有明确说明部分推导的参数包)模棱两可的函数指针在推导阶段被简单地丢弃,随后替换失败,因为它试图替换 3 个参数成一个推导的 2 参数函数。它永远不会到达需要解决歧义的地步。

关于c++ - 为什么编译器不给出不明确的引用错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44419508/

相关文章:

c++ - 将 unique_ptr 传递给函数对象

c++ - 构造函数参数的引用成员按值传递

c++ - 重载函数模板消歧与 `std::enable_if` 和非推断上下文

c++ - 为什么容器的分配器作为模板参数传递?

c++ - 函数模板的显式特化导致链接器错误

c++ - EXC_BAD_ACCESS:调用 Nan::Callback 时

C++ SIMD : Store uint64_t value after bitwise and operation

c++ - 关于不可推导的函数模板参数的误解

c++ - 虚函数错误(vtable?)

c++ - 词族