clang vs gcc:如何在clang中检查多个继承的第二父关系

时间:2017-10-16 09:29:03

标签: c++ templates gcc clang multiple-inheritance

是否有一种“最佳实践”方法来检查(在编译时)多继承关系中的非第一父关系?我用下面的例子来说明我的问题:

此代码是一种允许在多重继承中检查非第一父关系的方法,通过使用在GCC中工作的void指针比较技巧(6.3及以下:7.1及以上版本不允许)但不在clang(5.0.0):

#pragma clang diagnostic ignored "-Wreinterpret-base-class"

#include <cassert>
#include <type_traits>

struct Grandparent {
    int thing = 1;
    virtual void foo() {};
};

struct Parent1 : Grandparent {
    int thing = 2;
};

struct Parent2 : Grandparent {
    int thing = 3;
};

struct MIChild : public Parent1, public Parent2 {
    int thing = 4;
};

template <typename T1, typename T2>
class IsSameVoidPtr
{
    static constexpr T1* _p = nullptr;
    static constexpr bool Castable(std::true_type)
    {
        return static_cast<void*>(_p + 1) == static_cast<void*>(static_cast<T2*>(_p + 1));
    }
    static constexpr bool Castable(std::false_type) { return false; }
public:
    static constexpr bool value = Castable(std::integral_constant<bool,
        std::is_base_of<T1, T2>{} || std::is_base_of<T2, T1>{}>{});
};

int main() {
    MIChild test;
    Grandparent* gp_ptr = reinterpret_cast<Grandparent*>(&test);
    Parent1* p1_ptr = reinterpret_cast<Parent1*>(&test);
    Parent2* p2_ptr = reinterpret_cast<Parent2*>(&test);
    MIChild* ch_ptr = &test;
    static_assert(IsSameVoidPtr<Parent1, Grandparent>::value == true, "Failed P1 to G test");
    static_assert(IsSameVoidPtr<Parent2, Grandparent>::value == true, "Failed P2 to G test");
    static_assert(IsSameVoidPtr<Parent1, Parent2>::value == false, "Failed P1 to P2 test");
    static_assert(IsSameVoidPtr<MIChild, Parent1>::value == true, "Failed C to P1 test");
    static_assert(IsSameVoidPtr<MIChild, Parent2>::value == false, "Failed C to P2 test");
}

GCC编译它并按预期工作。它正确地看到第二个父项具有与子项以及第一个父项不同的void指针。

然而,clang不允许对空指针进行算术运算,这会导致整个错误链(我显示错误的第一个实例,其他错误都是相似的):

32 : <source>:32:27: error: constexpr variable 'value' must be initialized by a constant expression
    static constexpr bool value = Castable(std::integral_constant<bool,
                          ^       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
42 : <source>:42:19: note: in instantiation of template class 'IsSameVoidPtr<Parent1, Grandparent>' requested here
    static_assert(IsSameVoidPtr<Parent1, Grandparent>::value == true, "Failed P1 to G test");
                  ^
28 : <source>:28:38: note: cannot perform pointer arithmetic on null pointer
        return static_cast<void*>(_p + 1) == static_cast<void*>(static_cast<T2*>(_p + 1));
                                     ^
32 : <source>:32:35: note: in call to 'Castable({})'
    static constexpr bool value = Castable(std::integral_constant<bool,
                                  ^

0 个答案:

没有答案