c++ - 匹配派生类型而不是基类的模板方法

标签 c++ templates boost enable-if expression-templates

我有一组运算符,我需要为表达式模板覆盖这些运算符。我希望基类型的所有派生类都与基类型匹配。然后其他的东西会被通用类型捕获。不幸的是,泛型类型先于基类型获取派生类型。为了使事情变得美好和困惑,一切都被大量模板化,包括一些 CRTP。让我试着给出一个更简单的代码版本:

// Note: 'R' is used for return type
template <typename DerivedType, typename R>
class Base
{ // ...
};

template <typename E1, typename E2, typename R>
class MultOperation : public Base<MultOperation<E1, E2, R>, R>
{ // ...
};

template <typename T>
class Terminal : public Base<Terminal<T>, T>
{ // ...
};

// The broken operators:
template <typename T1, typename T2, typename R1, typename R2>
MultOperation<Base<T1, R1>, Base<T2, R2>, typename boost::common_type<R1, R2>::type>
operator*( Base<T1, R1> const& u, Base<T2, R2> const& v)
{
    return MultOperation<Base<T1, R1>, Base<T2, R2>, typename boost::common_type<R1, R2>::type>(u, v);
}

template <typename T1, typename T2, typename R1, typename R2>
MultOperation<Terminal<T1>, Base<T2, R2>, typename boost::common_type<T1, R2>::type>
operator*( T1 const& u, Base<T2, R2> const& v)
{
    return MultOperation<Terminal<T1>, Base<T2, R2>, typename boost::common_type<T1, R2>::type>(Terminal<T1>(u), v);
}

template <typename T1, typename T2, typename R1, typename R2>
MultOperation<Base<T1, R1>, Terminal<T2>, typename boost::common_type<R1, T2>::type>
operator*( Base<T1, R1> const& u, T2 const& v)
{
    return MultOperation<Base<T1, R1>, Terminal<T2>, typename boost::common_type<R1, T2>::type>(u, Terminal<T2>, v);
}

现在,我无法使用任何新的 C++ 功能。 (这是删除旧库的一些重构的一部分,因此我们可以升级到新的 cpp 标准。)不过我可以使用 boost 东西。我在想我的答案可能在于 boost::enable_if 东西,但我所有的尝试都进入了死胡同。现在,请记住,目标是表达式模板,所以我不能为传入的数据做任何转换。是的......它太复杂了......我希望你有一些魔法。

问题的简短版本: 我怎样才能得到 (1 * Derived) * Derived 以匹配第一个运算符的 operator(T, Base),然后是 operator(Base, Base) 对于第二个运算符(operator)? 它目前匹配第一个罚款,然后第二个匹配到一个 Base 泛型运算符,因为 T 不进行转换,因此比 Base 匹配得更好。

最佳答案

这是一个测试类是否是某种Base的特征:

template<class T>
struct is_some_kind_of_Base {
    typedef char yes;
    typedef struct { char _[2]; } no;

    template<class U, class V>
    static yes test(Base<U, V> *);
    static no test(...);

    static const bool value = (sizeof(test((T*)0)) == sizeof(yes));
};

然后约束后面的两个 operator*,例如:

template <typename T1, typename T2,  typename R2>
typename boost::disable_if<is_some_kind_of_Base<T1>,
                MultOperation<Terminal<T1>, Base<T2, R2>, 
                              typename boost::common_type<T1, R2>::type> >::type
operator*( T1 const& u, Base<T2, R2> const& v) { /* ... */ }

Demo .

为了防止 common_type 导致硬错误,我们需要推迟它的评估。

template <class T1, class T2, class R1, class R2>
struct make_mult_operation {
    typedef MultOperation<T1, T2, typename boost::common_type<R1, R2>::type> type;
};

template <typename T1, typename T2,  typename R2>
typename boost::disable_if<is_some_kind_of_Base<T1>,
                make_mult_operation<Terminal<T1>, T2, T1, R2> >::type::type
operator*( T1 const& u, Base<T2, R2> const& v) { /* ... */ }

Demo .

关于c++ - 匹配派生类型而不是基类的模板方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30202552/

相关文章:

c++ - 为什么所有 C++ 编译器都会因为这段代码而崩溃或挂起?

c++ - SFINAE 序列化共享指针失败

c++ - 为什么 scoped_ptr 不能与 STL 容器一起使用?

c++ - 从 C++11 中的容器元组中提取 value_type 的元组

C++ : How can I know the size of Base class SubObject?

c++ - 如何使策略决定成员变量类型?

C++ 返回对象,这可能吗?

c++ - 模板类调用了错误的复制构造函数

c++ - 关于 std::string Action 的实现

c++ - 使用 realloc 的动态内存重新分配