次の典型的な 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> >]