2017-06-07 5 views
2

は、私はまた、テンプレートクラス(あるそのうちのいくつかの異なるクラスで使用されているので、彼らがどのようなクラスの彼らについての完全な情報を持っていない可能性があり特化テンプレートクラスは

template <typename T> struct Parser { 
    //specializations are expected to have these methods 
    inline static const byte* objectEnd(const byte* begin, const byte* end); 
    inline static const byte* tryRead(const byte* begin, const byte* end, T* obj); 
} 

のようなテンプレート構造体を持っていると仮定を設定し、パラメータとしてParserに渡す)。任意のタイプのためにParserの実装
はこのように、簡単です:

template<> struct Parser<text_line> { 
    inline static const byte* objectEnd(const byte* begin, const byte* end){ 
    return helper::NextByteOrEnd<'\n'>(begin, end); 
    } 
    inline static const byte* tryRead(const byte* begin const byte* end, text_line* obj){ 
    const byte* lf = objectEnd(begin, end); 
    obj = text_line(begin, lf); 
    return lf==end ? lf : lf+1; 
    } 
} 

私も、テンプレートの家族のためにParserを特化することができます

template<int sz> struct Parser<be_uint<sz>> { 
    inline static const byte* objectEnd(const byte* begin, const byte* end){ 
    return begin+be_uint<sz>::size > end ? begin : begin+be_uint<sz>::size; 
    } 
    inline static const byte* tryRead(const byte* begin const byte* end, be_uint<sz>* obj){ 
    if(begin + be_uint<sz>::size > end) return begin; 
    obj = be_uint<sz>::read(begin); 
    return begin + be_uint<sz>::size; 
    } 
} 

しかし、何を私はParserを専門とする場合他のタイプのセット?良いアイデアのように見えるしていません

template <typename T, bool MyHeaderFlag = std::is_base_of<MyHeader, T>::value> 
struct Parser { //... 

のように、私は、std::is_base_of<MyHeader, T>を言う、タイプ述語を持っていると私はParserの初期定義にオプションのパラメータを追加する

//not actual code - how would I write this? 
template<typename Header> struct Parser<Header> { 
    static_assert(std::is_base_of<MyHeader, Header>::value, "Wrong!"); 
    inline static const byte* objectEnd(const byte* begin, const byte* end){ 
    //MyHeader-specific code here 
    } 
    inline static const byte* tryRead(const byte* begin const byte* end, Header* obj){ 
    //MyHeader-specific code here 
    } 
} 

のようなものを書きたいとしよう - 私(または他のプログラマー)は、他の述部、たとえばmy_types::is_scientific<T>を使用することができます。
問題はSFINAEで解決できるもののようです(1つのタイプがいくつかの述語に合っていれば何が起こるべきかという問題があります。コンパイラエラーは発生しませんが、それほど重要ではありません)Parser specializations .cpp-filesで見分けることができます)。しかし、私はこれを行う方法を見つけることができませんでした。

ただ、明確にするために

は、パーサ」またはそのメソッド(あるいはそれがテンプレートである) `の正確な定義を維持するには制約がない限り、クライアントのコードは次のような何かを書くことができるよう

Parser<TypeArg>::objectEnd(block.begin, block.begin+block.size) 

実際にはTypeArgを気にせずに。

+0

CPP-ファイル内のテンプレート機能を保管したりしないでください。https://stackoverflow.com/questions/115703/storing-c-template-function-definitions-in -a-cpp-file – Jonas

+1

@Jonas .cppファイルにテンプレートの特殊化(_including declaration_)を記述すると、それはどういう意味が間違っていますか? – Abstraction

答えて

2

いくつかの種類のセットを特殊化する場合は、2番目のテンプレートパラメータを基本テンプレートに追加するのが最善の方法です。

boolで、または実際に入力してstd::enable_ifを特殊化して使用できます。

私は第2の方法を好みます。

template <typename T, typename = void> struct Parser { 
    //specializations are expected to have these methods 
    inline static const byte* objectEnd(const byte* begin, const byte* end); 
    inline static const byte* tryRead(const byte* begin, const byte* end, T* obj); 
} 

と専門例

template<typename Header> 
struct Parser<Header, typename std::enable_if<std::is_base_of<MyHeader, Header>::value>::type> { 
    inline static const byte* objectEnd(const byte* begin, const byte* end){ 
    //MyHeader-specific code here 
    } 
    inline static const byte* tryRead(const byte* begin, const byte* end, Header* obj){ 
    //MyHeader-specific code here 
    } 
} 
関連する問題