Sfinae: обнаружить, имеет ли класс бесплатную функцию
Вопрос
Есть ли способ, используя SFINAE, чтобы определить, перегружена ли бесплатная функция для данного класса?
По сути, у меня есть следующее решение:
struct has_no_f { };
struct has_f { };
void f(has_f const& x) { }
template <typename T>
enable_if<has_function<T, f>::value, int>::type call(T const&) {
std::cout << "has f" << std::endl;
}
template <typename T>
disable_if<has_function<T, f>::value, int>::type call(T const&) {
std::cout << "has no f" << std::endl;
}
int main() {
call(has_no_f()); // "has no f"
call(has_f()); // "has f"
}
Просто перегрузка call
не работает, так как на самом деле много foo
а также bar
Типы и call
Функция не знает о них (в основном call
внутри А и пользователи предоставляют свои собственные типы).
Я не могу использовать C ++ 0x, и мне нужно рабочее решение для всех современных компиляторов.
Примечание: решение для Подобный вопрос К сожалению, здесь не работает.
Решение
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <functional>
#include <type_traits>
struct X {};
struct Y {};
__int8 f(X x) { return 0; }
__int16 f(...) { return 0; }
template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int8), int>::type call(T const& t) {
std::cout << "In call with f available";
f(t);
return 0;
}
template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int16), int>::type call(T const& t) {
std::cout << "In call without f available";
return 0;
}
int main() {
Y y; X x;
call(y);
call(x);
}
Быстрая модификация типов возврата f () дает традиционное решение Sfinae.
Другие советы
Если boost
разрешено, следующий код может соответствовать вашей цели:
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
using namespace boost;
// user code
struct A {};
static void f( A const& ) {}
struct B {};
// code for has_f
static void f(...); // this function has to be a free standing one
template< class T >
struct has_f {
template< class U >
static char deduce( U(&)( T const& ) );
template< class U, class V >
static typename disable_if_c< is_same< V, T >::value, char(&)[2] >::type
deduce( U(&)( V const& ) );
static char (&deduce( ... ))[2];
static bool const value = (1 == sizeof deduce( f ));
};
int main()
{
cout<< has_f<A>::value <<endl;
cout<< has_f<B>::value <<endl;
}
Однако существуют серьезные ограничения.
Код предполагает, что все пользовательские функции имеют подпись ( T const& )
, так ( T )
не допускается.
Функция void f(...)
В вышеперечисленном, кажется, должна быть функция свободного стояния.
Если компилятор обеспечивает двухфазный поиск, как и ожидалось, вероятно, все пользовательские функции должны появиться до определения has_f
Шаблон класса.
Честно говоря, я не уверен в полезности кода, но в любом случае я надеюсь, что это поможет.