2017-02-23 4 views
0

テンプレートクラスを作成しようとしています.1つまたは複数のタイプでインスタンス化されているかどうかによって、異なる署名付きのコールバックを実装します。enable_ifを使用した構造化テンプレートの特殊化

struct NoIntermediate 
{ 
}; 

template<typename R, typename I> 
struct ParserCallbackSwitch 
{ 
    using type = std::function<bool(const std::string &, R&, I&)>; 
} 

template<typename R, typename I = NoIntermediate> 
class OtherClass 
{ 
public: 
    typedef ParserCallbackSwitch<R, I>::type ParserType; 

} 

は、今私は、コードを追加したいので、ParserCallbackSwitchがあろうと、「OtherClass」インスタンス化するとき、私は指定されていない場合:この場合にはParserCallbackSwitch ::型が関数であることを

template<typename R, typename I> 
struct ParserCallbackSwitch 
{ 
     using type = std::function<bool(const std::string &, R&)>; 
} 

お知らせ2つのパラメータしかありません。

私は、次の操作を実行できるようにしたかった:

OtherClass<int, float> p; // p::ParserType = std::function<bool(std::string &, int &, float &); 
OtherClass<int> q;  // q::ParserType = std::function<bool(std::string &, int &); 

私はタイプNoIntermediateである場合に、部分的にケースのためParserCallbackSwitchを指定する方法を見つけ出すことはできません(つまり、私が指定されていない)

解決策:以下の回答に基づきます。ここで私は最終的に使い終わったコードです。

struct NoIntermediate {}; 

template<typename R, typename I = NoIntermediate> 
struct ParserCallbackSwitch 
{ 
    using type = std::function<bool(const std::string &, R&, I&)>; 
}; 

template<typename R> 
struct ParserCallbackSwitch<R, NoIntermediate> 
{ 
    using type = std::function<bool(const std::string &, R&)>; 
}; 

template<typename R, typename I = NoIntermediate> 
class OtherClass 
{ 
    public: 
    typedef ParserCallbackSwitch<R, I>::type ParserType; 
} 
+0

[パラメータパック](http://en.cppreference.com/w/cpp/language/parameter_pack)が必要なのでしょうか? –

答えて

1

だから!あなたはテンプレートを適切に専門化していません。同じ名前を持つ2つの無関係なクラステンプレートを定義しています。

提案する方法は複数あります。これは、最も特殊化されていないテンプレートにパラメータパックを与えます。

#include <functional> 
#include <type_traits> 

template<typename... S> 
struct OtherClass; 

template<typename R, typename I> 
struct OtherClass<R, I> { 
    using ParserType = std::function<bool(std::string&, R&, I&)>; 
}; 

template<typename R> 
struct OtherClass<R> { 
    using ParserType = std::function<bool(std::string&, R&)>; 
}; 

int main(void) { 
    static_assert(std::is_same<OtherClass<int, float>::ParserType, 
          std::function<bool(std::string&, int&, 
               float&)>>(), 
       "Something wrong here."); 
    static_assert(std::is_same<OtherClass<int>::ParserType, 
          std::function<bool(std::string&, int&)>>(), 
       "Hmmmmmm."); 
    return 0; 
} 

パラメータにデフォルトのタイプを使用してのあなたのアイデアも動作しますが、あなたの構文が少しオフでした。それはどのように見えるかです。

#include <functional> 
#include <type_traits> 

template<typename R, typename I = void> 
struct OtherClass { 
    using ParserType = std::function<bool(std::string&, R&, I&)>; 
}; 

template<typename R> 
struct OtherClass<R, void> { 
    using ParserType = std::function<bool(std::string&, R&)>; 
}; 

int main(void) { 
    static_assert(std::is_same<OtherClass<int, float>::ParserType, 
          std::function<bool(std::string&, int&, 
               float&)>>(), 
       "Something wrong here."); 
    static_assert(std::is_same<OtherClass<int>::ParserType, 
          std::function<bool(std::string&, int&)>>(), 
       "Hmmmmmm."); 
    return 0; 
} 
+0

閉じる、私はvoidを使用することはできません。コードの別の部分では、それを関数のパラメータとして使用しています。私がstruct NoIntermediate {}のデフォルトを使用すると、2つ目は完全に動作します。 私は最終的に上記を使用して終了コードを入れます。ありがとう! – bpeikes

関連する問題