, hierachy . SFINAE , . , , ; , SFINAE.
:
#include <iostream>
template < typename T >
struct has_foo
{
typedef char yes;
typedef char no[2];
struct fallback { int foo; };
struct mixed_type: T, fallback {};
template < typename U, U > struct type_check {};
template < typename U > static no& test( type_check< int (fallback::*),
&U::foo >* = 0 );
template < typename U > static yes& test( ... );
static const bool value = sizeof( yes ) ==
sizeof( test< mixed_type >( NULL ) );
};
namespace detail {
class yes {};
class no{ yes m[2]; };
struct helper {};
template < typename T > helper operator,( helper, const T& );
yes operator,( helper, yes );
no operator,( helper, no );
no operator,( no, yes );
}
template < typename T >
struct can_call_foo
{
struct fallback { ::detail::no foo( ... ) const; };
struct mixed_type: T, fallback
{
using T::foo;
using fallback::foo;
};
template < typename U, bool = has_foo< U >::value >
struct impl
{
static const bool value = sizeof( ::detail::yes ) ==
sizeof( ::detail::helper(),
((mixed_type*)0)->foo(),
::detail::yes() );
};
template < typename U >
struct impl< U, false >
{
static const bool value = false;
};
static const bool value = impl< T >::value;
};
struct B { void foo(); };
struct D1: B { bool foo(); };
struct D2: B { using B::foo; };
struct D3: B { };
struct F {};
struct G { int foo; };
struct G1 { bool foo( int ); };
int main ()
{
std::cout << "B: " << has_foo< B >::value << " - "
<< can_call_foo< B >::value << "\n"
<< "D1: " << has_foo< D1 >::value << " - "
<< can_call_foo< D1 >::value << "\n"
<< "D2: " << has_foo< D2 >::value << " - "
<< can_call_foo< D2 >::value << "\n"
<< "D3: " << has_foo< D3 >::value << " - "
<< can_call_foo< D3 >::value << "\n"
<< "F: " << has_foo< F >::value << " - "
<< can_call_foo< F >::value << "\n"
<< "G: " << has_foo< G >::value << " - "
<< can_call_foo< G >::value << "\n"
<< "G1: " << has_foo< G1 >::value << " - "
<< can_call_foo< G1 >::value << "\n"
<< std::endl;
return 0;
}
:
B: 1 - 1
D1: 1 - 1
D2: 1 - 1
D3: 1 - 1
F: 0 - 0
G: 1 - 0
G1: 1 - 0
has_foo foo. , foo (public member function public member, ).
can_call_foochecks if T::foo()called. If T::foo()it is not publicly available, a compiler error will occur. As far as I know, there is no way to prevent this through SFINAE. For a more complete and brilliant, but rather complex solution, here .
source
share