如何检测类型是否是另一种类型的可见基础?

时间:2012-03-27 18:19:57

标签: c++ templates inheritance

如果我这样做

struct A{};
struct C:private A{};

typedef char (&yes)[1];
typedef char (&no)[2];

template <typename B, typename D>
struct Host
{
 operator B*() const;
 operator D*();
};

template <typename B, typename D>
struct is_base_of
{
template <typename T> 
static yes check(D*, T);
static no check(B*, int);

static const bool value = sizeof(check(Host<B,D>(), int())) == sizeof(yes);
};

int main(){
 std::cout<<is_base_of<A,C>::value<<std::endl;
}

我得到1.我希望C为私有A时为0,而当C为公共A时为1。

[代码源自How does `is_base_of` work?]

3 个答案:

答案 0 :(得分:4)

您是否可以访问支持C ++ 11的编译器?

如果是这样,您可以将Chad使用static_castdecltype结合起来创建一个非常简单的类型特征实现(如this question中所示)。根据Jonathan Wakely的建议,当D定义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 {};

使用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;
}

答案 1 :(得分:0)

您是否需要可以在运行时评估的内容,或者简单的编译时错误是否足够?

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;
}

答案 2 :(得分:0)

为了应用编译时重载解析技巧来检测访问说明符,您至少需要在重载解析完成时考虑访问说明符。 C ++ 03 的情况并非如此,因此无法完成。我相信 C ++ 11 会通过一些人工转换和 SFINAE 来改变这一点。您可以实现它。

更新我正在查看 n3242 重载决策部分,我找不到任何可以指示访问说明符在C ++ 11中被认为是过载结果的内容