C++:如何要求一个模板类型派生自另一个

Wil*_*ill 14 c++ templates metaprogramming

在比较运算符中:

template<class R1, class R2>
bool operator==(Manager<R1> m1, Manager<R2> m2) {
    return m1.internal_field == m2.internal_field;
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以强制R1和R2必须有超类型或子类型关系?也就是说,我想允许R1从R2派生,或者R2从R1派生,但如果R1和R2是不相关的类型,则不允许比较.

GMa*_*ckG 24

你想要的特征可能如下所示:

template <typename B, typename D>
struct is_base_of // check if B is a base of D
{
    typedef char yes[1];
    typedef char no[2];

    static yes& test(B*);
    static no& test(...);

    static D* get(void);

    static const bool value = sizeof(test(get()) == sizeof(yes);
};
Run Code Online (Sandbox Code Playgroud)

那么你只需要某种静态断言:

// really basic
template <bool>
struct static_assert;

template <>
struct static_assert<true> {}; // only true is defined

#define STATIC_ASSERT(x) static_assert<(x)>()
Run Code Online (Sandbox Code Playgroud)

然后将两者放在一起:

template<class R1, class R2>
bool operator==(Manager<R1> m1, Manager<R2> m2)
{
    STATIC_ASSERT(is_base_of<R1, R2>::value || is_base_of<R2, R1>::value);

    return p1.internal_field == p2.internal_field;
}
Run Code Online (Sandbox Code Playgroud)

如果一个不从另一个派生,则该函数将无法编译.(您的错误类似于" static_assert<false>未定义",它将指向该行.)

  • 狡猾.(最后一行应该是'static_assert <false>'而不是'static_cast <false>,对吗?) (2认同)
  • @Noah:是的,但是我们不需要首先制作一个.:) (2认同)

Unc*_*ens 21

你可以使用boost的typetraits(is_base_of)和boost的enable_if.

#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>

template <class R1, class R2>
struct has_derived_base_relationship :
    boost::integral_constant<
        bool, boost::is_base_of<R1, R2>::value || boost::is_base_of<R2, R1>::value 
    >
{};

template<class R1, class R2>
typename boost::enable_if<has_derived_base_relationship<R1, R2>, bool>::type 
operator==(Manager<R1> m1, Manager<R2> m2) {
    return p1.internal_field == p2.internal_field;
}
Run Code Online (Sandbox Code Playgroud)

另一方面,为什么operator == usage对同一继承树的类型有更多价值?是不是必须使用双重调度才能取得有意义的结果?