C++:可以在编译时检测虚拟继承吗?

Tim*_*Tim 22 c++ templates

我想在编译时确定是否可以从没有dynamic_cast <>的指针转换为指向Derived的指针.这可能使用模板和元编程吗?这与确定Base是否是Derived的虚拟基类不完全相同,因为Base可能是Derived虚拟基类的超类.

谢谢Tim更新:我觉得这个方法很好:

#include <iostream>

using namespace std;

class Foo
{
};

class Bar : public Foo
{
};

class Baz : public virtual Foo
{
};

class Autre : public virtual Bar
{
};

typedef char Small;
class Big { char dummy[2]; };

template<typename B, typename D>
struct is_static_castable
{
    const B* foo;
    char bar[1];
    static Small test(char(*)[sizeof(static_cast<const D*>(foo)) == sizeof(const D*)]);
    static Big test(...);
    enum { value = (sizeof(test(&bar)) == sizeof(Small)) };
};

int main()
{

    cout << "Foo -> Bar: " << is_static_castable<Foo, Bar>::value << "\n";
    cout << "Foo -> Baz: " << is_static_castable<Foo, Baz>::value << "\n";
    cout << "Foo -> Autre: " << is_static_castable<Foo, Autre>::value << "\n";
}
Run Code Online (Sandbox Code Playgroud)

但它不适用于gcc:

multi-fun.cpp: In instantiation of ‘is_static_castable<Foo, Baz>’:
multi-fun.cpp:38:   instantiated from here
multi-fun.cpp:29: error: cannot convert from base ‘Foo’ to derived type ‘Baz’ via virtual base ‘Foo’
multi-fun.cpp:29: error: array bound is not an integer constant
multi-fun.cpp: In instantiation of ‘is_static_castable<Foo, Autre>’:
multi-fun.cpp:39:   instantiated from here
multi-fun.cpp:29: error: cannot convert from base ‘Foo’ to derived type ‘Autre’ via virtual base ‘Bar’
multi-fun.cpp:29: error: array bound is not an integer constant
Run Code Online (Sandbox Code Playgroud)

我对使用sizeof()技巧可以做些什么感到困惑?

mef*_*fiX 11

我有同样的问题,一次.不幸的是,我不太确定虚拟问题.但是:升压有一个名为类is_base_of(见这里),这将使你做不便.如下

BOOST_STATIC_ASSERT((boost::is_base_of<Foo, Bar>::value));
Run Code Online (Sandbox Code Playgroud)

此外,还有一类is_virtual_base_of在Boost的type_traits,也许这就是你要找的内容.

  • @Mike:你在哪里得到这个想法?C++的主要优势之一是可用的大量高质量库.看看其他一些C++问题,你会发现左右提示.如果问题是他们不能使用第三方库,那就是另一个故事. (18认同)
  • 即使你不想要lib,你也至少可以看看它们是如何实现它的. (4认同)

bra*_*ing 5

这是一个解决方案,用于重定向编译器以执行某些操作,具体取决于该类是否是另一个的子类.

class A 
{};

class B : virtual public A
{};

class C : public A
{};

// Default template which will resolve for 
// all classes
template 
< typename T
, typename Enable = void 
>
struct FooTraits
{
    static void foo(){
        std::cout << "normal" << std::endl;
    }
};

// Specialized template which will resolve
// for all sub classes of A
template 
< typename T 
>
struct FooTraits 
    < T
    , typename boost::enable_if
         < boost::is_virtual_base_of< A, T>
         >::type
    >
{
    static void foo(){
        std::cout << "virtual base of A" << std::endl;
    }
};

int main(int argc, const char * argv[] ){
    FooTraits<C>::foo(); // prints "normal"
    FooTraits<B>::foo(); // prints "virtual base of A"
}
Run Code Online (Sandbox Code Playgroud)

如果你想知道增压是如何做到的.如果您有类Base和类Derived,那么以下内容成立.

struct X : Derived, virtual Base 
{
   X();
   X(const X&);
   X& operator=(const X&);
   ~X()throw();
};

struct Y : Derived 
{
   Y();
   Y(const Y&);
   Y& operator=(const Y&);
   ~Y()throw();
};

bool is_virtual_base_of = (sizeof(X)==sizeof(Y)));
Run Code Online (Sandbox Code Playgroud)

这是使用具有多重继承性的虚拟继承的技巧.来自同一虚拟基础的多重继承不会导致虚拟基类的重复,因此您可以使用sizeof对其进行测试.