2016-08-19 16 views
1

私は最後の数日間直面するプログラミングの頭痛の助けを求めます。私が実装しようとしていることを説明しようとしましょう...Functors operator()の条件付き特殊化

私の目標は、妥当性を持つ一連の方程式を定義することです。もっと詳しく説明しましょう...

私は各等式オブジェクトがファンクタであると考えています - operator()を定義するクラスです。この演算子の定義は、各方程式タイプに特化している必要があります。専門は計算自体が含まれています

.H:

enum class IDs : int { A = 0, B = 1, C = 2 }; 

template<IDs WHICH> 
struct Equation 
{ 
    int operator() (void); 
} 

た.cpp:?あなたは気づいているかもしれませんが

template<> 
Equation<IDs::A>::operator()(void) 
{ 
    /* Just some sample equation */ 
    return(42 + 28); 
} 

、専門は::列挙型クラスのメンバーIDによって定義されます。

これは動作しているようです。しかし、私はいわゆる可用性機能を追加したいと思っています - 方程式は特定のユーザオブジェクトタイプに対してのみ有効です。

There is 'validity group' declared: 
/* Object types declaration */ 
namespace Objects { 
    using Object0 = boost::mpl::int_<0>; 
    using Object1 = boost::mpl::int_<1>; 
    using Object2 = boost::mpl::int_<2>; 
} 
/* Validity groups declaration */ 
using ValidityGroup1 = boost::mpl::vector<Object0, Object2>; 
using ValidityGroup2 = boost::mpl::vector<Object1>; 

(boost :: enable_ifを使用して)クラスを有効または無効にするために、次の構造を使用しています。ただ、私はそれを使用する方法を示すために:

template<typename TYPE_LIST, typename QUERY_TYPE> 
struct IsTypeInList 
{ 
    using TypePos = typename boost::mpl::find<TYPE_LIST, QUERY_TYPE>::type; 
    using Finish  = typename boost::mpl::end<TYPE_LIST>::type; 
    using type  = typename boost::mpl::not_<boost::is_same<TypePos, Finish> >::type; 
    using value_type = typename type::value_type; 

    static const bool value = type::value; 
}; 

template<typename OBJECT_TYPE, typename ENABLER=void> 
class SampleClass; 

template<typename OBJECT_TYPE> 
class SampleClass<OBJECT_TYPE, typename boost::enable_if<typename IsTypeInList<ValidityGroup1, Object0>::type>::type> 
{} 

SampleClassの部分特殊化はObject0ValidityGroup1に属している場合にのみ使用可能です。ここまでは順調ですね。この原則が確認されています。

今、面白いことが起こります。私は二つのことを一緒にマージしたいと思います:

GOAL:

は、(式の演算子を定義します)有効な体を含む専門はIDが::によって定義されます?列挙型クラス値 "であり、ValidityGroupに属するObjectに対してのみ使用可能です。同じID :: ??の別の計算がありますが、他のValidityGroup(Object0のプロパティはObject1とは別の方法で計算されます)のObjectに対して有効です。

私は、全体のコンセプトは非常に複雑であり、混乱を招くことがあり知っている私はこのようなものを実装するために私の試み見せしましょう:。

template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID, typename ENABLER = void> 
class Equation; 

template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID> 
class Equation<OBJECT_TYPE, VALIDITY_GROUP, ID, typename boost::enable_if<typename IsTypeInList<VALIDITY_GROUP, OBJECT_TYPE>::type>::type > 
: public EquationBase<IDs> 
{ 
public: 
int operator() (void); 
}; 

template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID> 
int Equation<OBJECT_TYPE, ValidityGroup1, Ids::A>::operator() (void) 
{ 
    return(42 + 56); 
} 

しかし、演算子()の定義が動作していないが...あなたがアドバイスしてもらえ私はこれを働かせるにはどうすればいいのですか?また、上記の目標をどのように達成するか他の誰かが考えていますか?

多くのおかげで私を助けるために喜んで誰にも事前に ...

乾杯マーティン

EDIT: 式はテンプレートクラスのオブジェクトで使用されています。

template<typename OBJECT_TYPE> 
class Object 
{ 
public: 
    Object(void); 
}; 

た.cpp:とき演算子()

template<typename OBJECT_TYPE> 
Object<OBJECT_TYPE>::Object(void) 
{ 
    std::cout << Equation<IDs::A>()() << std::endl; 
} 

問題がOBJECT_TYPEあるが定義されていないが、特化され...

答えて

1

私はあなたが望むものを正しく理解していれば、コードを説明しましょう取得するには、私は多くの方法があると思います。

次はIPER-semplified例である(しかし、完全な広告が働い)std::enable_ifを使用して異なる実装を選択する方法を示します(ただしboost::enable_ifがOKでなければなりません)そのオペレータ本当に

#include <iostream> 
#include <type_traits> 

template <typename ObjT, typename ValT> 
class Equation 
{ 
    public: 
     template <typename X = ObjT> 
     typename std::enable_if<true == std::is_same<X, ValT>::value, int>::type 
     operator() (void) 
      { return(0); } 

     template <typename X = ObjT> 
     typename std::enable_if<false == std::is_same<X, ValT>::value, int>::type 
     operator() (void) 
      { return(1); } 
}; 

int main() 
{ 
    Equation<int, int> eq0; 
    Equation<int, long> eq1; 

    std::cout << "eq0 val: " << eq0() << std::endl; // print "eq0 val: 0" 
    std::cout << "eq1 val: " << eq1() << std::endl; // print "eq1 val: 1" 
} 

ないの戻り値の型を持ちますエレガント、私は思います。

別の解決策は、(それは、私が思う、最良のあなたの要望に合った)クラス部分特殊化に基づいて、次の

#include <iostream> 
#include <type_traits> 


template <typename ObjT, typename ValT, bool = std::is_same<ObjT, ValT>::value> 
class Equation; 

template <typename ObjT, typename ValT> 
class Equation<ObjT, ValT, true> 
{ 
    public: 
     int operator()(); 
}; 

template <typename ObjT, typename ValT> 
class Equation<ObjT, ValT, false> 
{ 
    public: 
     int operator()(); 
}; 


template <typename ObjT, typename ValT> 
int Equation<ObjT, ValT, true>::operator()() 
{ return(0); } 

template <typename ObjT, typename ValT> 
int Equation<ObjT, ValT, false>::operator()() 
{ return(1); } 

int main() 
{ 
    Equation<int, int> eq0; 
    Equation<int, long> eq1; 

    std::cout << "eq0 val: " << eq0() << std::endl; // print "eq0 val: 0" 
    std::cout << "eq1 val: " << eq1() << std::endl; // print "eq1 val: 1" 
} 
+0

感謝Max66かもしれません!私は待っています:o)楽しみにしています。たぶん、考慮すべきもう一つの事柄...方程式はテンプレート化されたクラスによって所有されており、所有者オブジェクトのテンプレートパラメータに基づいて適切なoperator()の実装を選択することは素晴らしいことでしょう... edit in my origial post ... –

+0

@MartinKopecký - 別の例が追加されました。申し訳ありませんが、あなたは「何かが好きです:」はあなたのコメントの最後の部分です。私はあなたが望むものを理解していません。私はあなたが質問を修正するか、(もしあなたの次のdesiderataが本当に違うなら)別の質問を挿入してください。 – max66

+0

申し訳ありません私はオリジナルの投稿を編集するのが遅かった...あなたの努力のために多くのおかげです、私は今、私の話題についてちょっと混乱していると感じています。:o) –