Рассматривается ли это SFINAE?
Я задал вопрос о неделю назад, спрашивая, как я могу просто создать экземпляр шаблона класса, только если тип, который у него был, имел определенную функцию-член. В моем ответе я получил своеобразное сложное решение. Но потом я попытался сделать это сам. Я просто хотел знать, имеет ли это достаточно, чтобы выяснить из данного типа T
, имеет функцию void с именем f
, принимающую 0 параметров.
#include <type_traits>
#include <utility>
template <typename T, typename = void>
struct has_f : std::false_type { };
template <typename T>
struct has_f<
T,
decltype(std::declval<T>().f(), void())> : std::true_type { };
template <typename T, typename = typename std::enable_if<has_f<T>::value>::type>
struct A { };
struct B
{
void f();
};
struct C { };
template class A<B>; // compiles
template class A<C>; // error: no type named ‘type’
// in ‘struct std::enable_if<false, void>’
Если да, то почему другие ответы настолько сложны в этом потоке?
Ответы
Ответ 1
Да, вы решили его в простейшем, наиболее идиоматическом стиле С++ 11 SFINAE.
Обратите внимание, что вы не проверяли, что тип возвращаемого значения void
, что он является нестатическим членом, и что нет параметров. f
просто вызывается без аргументов. Это может быть даже функтор.
Чтобы проверить, что нестатическая функция с нулевым членом возвращает void
, используйте
template <typename T>
struct has_f<T, decltype(void( static_cast< void (T::*)( void ) >( &T::f ) )) >
: std::true_type {};
template <typename T>
struct has_f<T, decltype(void( static_cast< void (T::*)( void ) const >( &T::f ) )) >
: std::true_type {};