Consider the following typical test function, SFINAE (it checks to see if the member function has a type 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; }
I can call this an argument:
has_begin_member <int> (0);
but without any arguments:
has_begin_member <int> ();
this leads to the following ambiguity:
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())*)
Why does the "elliptical trick" not work in this case?
Edit: full program:
#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 (){}
Compilation:
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> >]
source share