gpt4 book ai didi

c++ - SFINAE:如果不带参数调用,则会出现不明确的重载

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:04:26 24 4
gpt4 key购买 nike

考虑以下典型的 SFINAE 测试函数(它检查类型是否具有 begin() 成员函数)

    template <class> constexpr bool
has_begin_member (...) { return false; }

template <class T> constexpr bool
has_begin_member (decltype (std::declval <T>().begin ())* = 0) {
return true;
}

我可以用参数调用它:

has_begin_member <int> (0); // yields false

但没有任何参数:

has_begin_member <int> (); // compilation error

它会导致以下歧义:

error: call of overloaded 'has_begin_member()' is ambiguous
note: candidates are:
note: constexpr bool has_begin_member(...)
note: constexpr bool has_begin_member(decltype (declval<T>().begin())*)

为什么“省略号技巧”在那种情况下不起作用?

编辑:完整程序:

#include <utility>
#include <vector>

template <class> constexpr bool
has_begin_member (...) { return false; }

template <class T> constexpr bool
has_begin_member (decltype (std::declval <T>().begin ())* = 0) {
return true;
}


static_assert (!has_begin_member <int> (0), "broken");
static_assert (has_begin_member <std::vector <int>> (0), "broken");

static_assert (!has_begin_member <int> (), "broken");
static_assert (has_begin_member <std::vector <int>> (), "broken");

int
main (){}

编译:

g++ -std=c++11 -o toto ./toto.cpp
./toto.cpp:17:58: error: call of overloaded 'has_begin_member()' is ambiguous
./toto.cpp:17:58: note: candidates are:
./toto.cpp:5:5: note: constexpr bool has_begin_member(...) [with <template-parameter-1-1> = std::vector<int>]
./toto.cpp:8:5: note: constexpr bool has_begin_member(decltype (declval<T>().begin())*) [with T = std::vector<int>; decltype (declval<T>().begin()) = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]

最佳答案

对于 has_begin_member<int>()如果第二个重载不可行,因为模板参数替换失败,那么只有第一个重载是可行的,所以没有歧义。

对于 has_begin_member<std::vector<int>>()案例替换成功,因此有两个可行的功能。

13.3.2 [over.match.viable]:

  • If there are m arguments in the list, all candidate functions having exactly m parameters are viable.
  • A candidate function having fewer than m parameters is viable only if it has an ellipsis in its parameter list (8.3.5). For the purposes of overload resolution, any argument for which there is no corresponding parameter is considered to “match the ellipsis” (13.3.3.1.3) .
  • A candidate function having more than m parameters is viable only if the (m+1)-st parameter has a default argument (8.3.6). For the purposes of overload resolution, the parameter list is truncated on the right, so that there are exactly m parameters.

在这种情况下 m 为零,第一个重载是可行的(通过第二个项目符号)并且第二个重载也是可行的(通过第三个项目符号)但是为了重载决议的目的,参数忽略默认参数,因此通过比较找到最佳可行函数:

template<> constexpr bool has_begin_member<vector<int>>(...);
template<> constexpr bool has_begin_member<vector<int>>();

这显然是有歧义的,就像这样:

int f(...);
int f();

int i = f(); // error

调用任何一个函数都不需要转换序列,因此不能根据哪个具有比另一个“更好的转换序列”来对它们进行排名(使用 13.3.3.2 [over.ics.rank] 中的规则)这意味着它们是模棱两可的。

关于c++ - SFINAE:如果不带参数调用,则会出现不明确的重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12109471/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com