If I do
struct A{};
struct C:private A{};
typedef char (&yes)[1];
typedef char (&no)[2];
template
struct Host
{
operato
Do you need something that can be evaluated at runtime, or will a simple compile time error suffice?
struct A {};
struct B : private A {};
int main()
{
B b;
// gives error C2243: 'static_cast' : conversion from 'B *' to 'A &' exists, but is inaccessible
A& a = static_cast<A&>(b);
return 0;
}
In order to apply the compile-time overload resolution trick to detect access specifiers, you would at least need that access specifiers are considered at the time overload resolution is done. This is not the case with C++03, so it cannot be done. I believe C++11 changes this so with some artificial conversions and SFINAE you would be able to implement it.
Update: I'm going over n3242 Overload Resolution section, and I cannot find anything that would indicate that access specifiers are considered for overload resultion at C++11.
Do you have access to a compiler with C++11 support?
If so, you can combine Chad's use of static_cast
with decltype
to create a very simple type trait implementation (as demonstrated in this question). As per Jonathan Wakely's suggestion, the references have been replaced with pointers to avoid false positives when D
defines an operator B&()
.
template<typename> struct AnyReturn { typedef void type; };
template<typename B, typename D, typename Sfinae = void>
struct is_base_of: std::false_type {};
template<typename B, typename D>
struct is_base_of<B, D,
typename AnyReturn< decltype( static_cast<B*>( std::declval<D*>() ) ) >::type
>: std::true_type {};
When using gcc 4.7:
struct Base {};
struct PublicDerived : public Base {};
struct PrivateDerived : private Base {};
int main()
{
std::cout << is_base_of<Base, PublicDerived >::value << std::endl; // prints 1
std::cout << is_base_of<Base, PrivateDerived>::value << std::endl; // prints 0
return 0;
}