В ответ на ... какой-то другой вопрос где-то я написал этот код.
struct no_type{};
template<typename T> struct has_apply {
static decltype(T().apply<0u>(double())) func( T* ptr );
static no_type func( ... );
static const bool result = !std::is_same<no_type, decltype(func(nullptr))>::value;
};
class A {
public:
template< unsigned n >
void apply( const double& );
};
class B {
};
int main()
{
std::cout << std::boolalpha << has_apply< A >::result << '\n';
std::cout << std::boolalpha << has_apply< B >::result << '\n';
std::cin.get();
return( 0 );
}
Теперь мне кажется, что результат должен быть истинным, если T предлагает нестатическую функцию-член «применить», которая принимает двойное значение rvalue и литерал параметра шаблона, и ложь в противном случае. Однако приведенный пример фактически не компилируется для класса B при компиляции has_apply<B>
. Не должен ли тот факт, что подстановка T в операторе decltype завершилась неудачно, означать, что он просто вызывает другую функцию? Разве не в этом суть SFINAE?
Решается самым нелепым и бессмысленным способом:
struct no_type{};
template<typename T> struct has_apply {
template<typename U> static decltype(U().apply<0u>(double())) func( U* );
template<typename U> static no_type func( ... );
static const bool result = !std::is_same<no_type, decltype(func<T>(nullptr))>::value;
};
class A {
public:
template< unsigned n >
void apply( const double& );
};
class B {
};
int main()
{
std::cout << std::boolalpha << has_apply< A >::result << '\n';
std::cout << std::boolalpha << has_apply< B >::result << '\n';
std::cin.get();
return( 0 );
}