4

私は現在、小さなメタプログラミング ベースのコンパイル時計算ライブラリを実装しています。

結果の typedef を持つ演算子の基本クラスを定義した場合 (std::integral_constantライブラリに沿って統一されたインターフェイスを提供するために、生の整数値の代わりに as 値のような積分ラッパーを使用することにしました)、および n-ary 演算子の基本クラスを定義した場合、演算子に少なくとも 1 つのオペランドがあるかどうかをチェックします。

template<typename RESULT>
struct operator
{
    using result = RESULT;
};

template<typename RESULT , typename... OPERANDS>
struct nary_operator : public operator<RESULT>
{
    static_assert( sizeof... OPERANDS > 0 , "An operator must take at least one operand" );
};

そこで、単項演算子と二項演算子のエイリアスを次のように定義しました。

template<typename OP , typename RESULT>
using unary_operator = nary_operator<RESULT , OP>;

template<typename LHS , typename RHS , typename RESULT>
using binary_operator = nary_operator<RESULT , LHS , RHS>;

その演算子インターフェイスは、以下の比較演算子のように、カスタム演算子をエイリアスとして定義するために使用されます。

template<typename LHS , typename RHS>
using equal = binary_operator<LHS,RHS,bool_wrapper<LHS::value == RHS::value>>;

template<typename LHS , typename RHS>
using not_equal = logical_not<equal<LHS,RHS>>;

template<typename LHS , typename RHS>
using less_than = binary_operator<LHS,RHS,bool_wrapper<LHS::value < RHS::value>>;

template<typename LHS , typename RHS>
using bigger_than = less_than<RHS,LHS>;

template<typename LHS , typename RHS>
using less_or_equal = logical_not<bigger_than<LHS,RHS>>;

template<typename LHS , typename RHS>
using bigger_or_equal = logical_not<less_than<LHS,RHS>>;

ここで、独自のクラスにカスタムの等価演算子を実装するとします。例えば:

template<typename X , typename Y , typename Z>
struct vec3
{
    using x = X;
    using y = Y;
    using z = Z;
}; 

等価演算子がエイリアシングではなく継承時に作成された場合、これはテンプレートの特殊化によって簡単に実行できます。

//Equality comparator implemented through inheritance:
template<typename LHS , typename RHS>
struct equal : public binary_operator<LHS,RHS,bool_wrapper<LHS::value == RHS::value>> {};

//Specialization of the operator for vec3:

template<typename X1 , typename Y1 , typename Z1 , typename X2 , typename Y2 , typename Z2>
struct equal<vec3<X1,Y1,Z1>,vec3<X2,Y2,Z2>> : public binary_operator<vec3<X1,Y1,Z1>,vec3<X2,Y2,Z2> , bool_wrapper<X1 == X2 && Y1 == Y2 && Z1 == Z2>> {}; 

テンプレート エイリアスを特殊化できないことはわかっています。
私の質問は次のとおりです。テンプレート エイリアスの代わりに継承設計を使用せずに、この種のテンプレート エイリアスを特殊化する方法はありますか?

4

3 に答える 3

2

これが古い質問であることは知っていますが、これは一般的な問題であり、このスレッドには今のところ満足のいく答えがありません...そのため、特定の質問ではなく一般的な問題に対処するものを提供しようとします( C++14 が必要です)。

namespace impl
{
    template<typename ... Args> struct A;
    template<typename T> struct A<T>
    {
        A() {std::cout<<"I'm an A"<<std::endl;}
    };

    template<typename ... Args> struct B;
    template<typename T, typename V> struct B<T, V>
    {
        B() {std::cout<<"I'm a B"<<std::endl;}
    };
}

template<typename ... Args>
using C = std::conditional_t<sizeof...(Args)==1
                          , typename impl::A<Args ...>
                          , typename impl::B<Args ...> >;

int main()
{
    C<double> a;            //prints "I'm an A"
    C<double, int> b;       //prints "I'm a B"
}

デモ

コードは自明である必要があります。主なアイデアは、引数の数に基づいて型を静的に選択することです。Aとの可変引数宣言が必要です。そうしないと、コンパイラは、1 つのパラメーターまたは2 つのパラメーターを持つ をそれぞれBインスタンス化できないと文句を言います。BA

このアプローチは確かに完全に一般的ではありません-デフォルトの引数または特殊化を考えてくださいB-しかし、おそらくそのような状況を処理するために拡張することもできます. それにもかかわらず、私はそれが自分のコーディングに役立つことがあると感じました。

于 2015-03-28T11:13:51.977 に答える
0

型エイリアスを特殊化することはできませんが、目的が構文的に特性を単純化することである場合は、私のようにそれを行うことができます。関連する特性を anit-pattern である BLOB に結合しますが、特殊化ではなく BLOB 自体で継承を使用して特性をオーバーライドします

#define DEFINE_TRAIT(TraitClass,TraitName)                             \
template<typename... T> using TraitName = typename TraitClass<T...>::TraitName

DEFINE_TRAIT(BinaryOpTrait, equal);
DEFINE_TRAIT(BinaryOpTrait, not_equal);
...
...

template<typename LHS , typename RHS>
struct BinaryOpTraitBase
{
    using equal = binary_operator<LHS,RHS,bool_wrapper<LHS::value == RHS::value>>;
    using not_equal = logical_not<::equal<LHS,RHS>>;
    ...
    ...
};
template<typename LHS , typename RHS>
struct BinaryOpTrait : BinaryOpTraitBase <LHS, RHS> {};

typename<>
struct BinaryOpTrait<vec3, vec3> : BinaryOpTraitBase<vec3, vec3>
{
    using equal = /* custom op */
};


//Usage:
    if(equal<int,int>(1,1))
        ...
    if(equal<vec3,vec3>(v1,v1)  //uses specialized
        ...
于 2013-07-26T02:13:22.270 に答える