模板匹配方法派生类型,而不是基地 [英] template method matching derived type instead of base

查看:135
本文介绍了模板匹配方法派生类型,而不是基地的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一组,我需要覆盖前pression模板运营商。我想一个基本类型匹配的基本类型的所有派生类。其他的事情然后由泛型类型被抓。不幸的是,基本类型做之前泛型类型抓住派生类型。为了让这件事情扑朔迷离,一切都是模板pretty巨资,其中包括一些CRTP。让我试着给code更简单的版本:

I have a set of operators that I need to override for expression templating. I would like all derived classes of a base type match to the base type. Other things would then be caught by a generic type. Unfortunately, the generic type grabs the derived types before the base type does. To make things nice and confusing, everything is templated pretty heavily, including some CRTP. Let me try to give a more simple version of the code:

// 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 ++功能。 (这是一些refactors删除旧的库,所以我们可以升级到新的标准的cpp的一部分)。我可以使用提升的东西,虽然。我想我的答案可能会在说谎的boost :: enable_if 的东西,但我所有的尝试都导致死角。现在,请记住我们的目标是前pression模板,所以我不能做数据进来任何东西铸造。是啊...它是如此复杂......我希望你有一些法宝你的袖子。

Now, I can't use any new C++ features. (This is part of some refactors to remove old libraries so we can upgrade to the new cpp standards.) I can use boost stuff, though. I was thinking my answer might lie in boost::enable_if stuff, but all my attempts have led to dead ends. Now, keep in mind that the goal is expression templates, so I can't do any casting stuff for data coming in. Yeah... it's so complicated... I hope you have some magic up your sleeve.

短版的问题:
我怎样才能获得(1 *派生)*衍生来匹配操作符(T,基地)第一个操作员,那么运营商(基地,基地)第二运营商?
目前,它匹配的第一个好,然后到基地,通用运营商之一的第二场比赛,而不是,为T概不转换,从而匹配比Base更好。

Short version of the question: How can I get (1 * Derived) * Derived to match to operator(T, Base) for the first operator, then operator(Base, Base) for the second operator? It currently matches the first fine, then the second matches to one of the Base-generic operators instead, as T takes no conversion and thereby matches better than Base.

推荐答案

下面是测试一个类是否是某种基本的特点:

Here's a trait that tests whether a class is some kind of 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));
};

然后你的约束后两个运算符* 就像:

And then constrain your later two operator*s like:

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) { /* ... */ }

演示

要prevent common_type 从导致一个严重的错误,我们需要推迟的评价。

To prevent common_type from causing a hard error, we need to defer its evaluation.

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) { /* ... */ }

演示

这篇关于模板匹配方法派生类型,而不是基地的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆