2

私はちょうどテンプレートメタプログラミングから始まり、文字列クラスを作成しています。あまりにも多くのテンプレート関連の問題なしにToString、Concat、CharAt、Lengthを実装しました。私は次のようにサブストリングを実装しようとしていた。C++テンプレートメタプログラミング特化曖昧さ

struct Null; 

// String class definition 
template <char C, class S> 
struct String { 
    static const char chr = C; 
    typedef S tail; 
}; 

// Substring 
// Gets the substring of length L starting at index I from string S. 
template <int I, int L, class S> 
struct Substring; 

template <class S> 
struct Substring<0, 0, S> { 
    typedef Null substr; 
}; 

// Will also cover I < 0 case 
template <int I, int L> 
struct Substring<I, L, Null> { 
    typedef Null substr; 
}; 

template <int L, char C, class S> 
struct Substring<0, L, String<C, S> > { 
    typedef String<C, typename Substring<0, L-1, S>::substr> substr; 
}; 

template <int I, int L, char C, class S> 
struct Substring<I, L, String<C, S> > { 
    typedef typename Substring<I-1, L, S>::substr substr; 
}; 

int main() { 
    // This all works... 
    typedef String<'H', String<'e', String<'l', String<'l', 
      String<'o', Null> > > > > hello; 
    typedef String<',', String<' ', Null> > comma; 
    typedef String<'w', String<'o', String<'r', String<'l', String<'d', 
      String<'!', Null> > > > > > world; 
    typedef Concat<hello, Concat<comma, world>::newstr>::newstr hello_world; 
    // ...up to here. 
    typedef Substring<3, 5, hello_world>::substr mystr; 
    return 0; 
} 

私はコンパイルするとき、私は曖昧エラーを取得:

template.cpp:161: error: ambiguous class template instantiation for ‘struct 
    Substring<0, 0, String<'o', String<'r', String<'l', String<'d', String<'!', 
    Null> > > > > >’ 
template.cpp:149: error: candidates are: struct Substring<0, 0, S> 
template.cpp:160: error:     struct Substring<0, L, String<C, S> > 
template.cpp:165: error:     struct Substring<I, L, String<C, S> > 
template.cpp:161: error: invalid use of incomplete type ‘struct Substring<0, 0, 
    String<'o', String<'r', String<'l', String<'d', String<'!', Null> > > > > >’ 
template.cpp:146: error: declaration of ‘struct Substring<0, 0, String<'o', 
    String<'r', String<'l', String<'d', String<'!', Null> > > > > >’ 
template.cpp: In function ‘int main()’: 
template.cpp:197: error: template argument 1 is invalid 

私は少し混乱しています。私は、テンプレートの専門化の全体のポイントは、このようなものをすることだと思った。これは単に次のような拡張子ではありません:

template <int N> 
struct Foo { ... } 

template <> 
struct Foo<0> { ... } 

この曖昧さを修正するにはどうすればよいですか?

ありがとうございました。ここで

+1

mmmm。私はこのコードを見て疲れました。私の好みにはあまりにも実用的ではありません。私はあなたがMPLを学ぶためにそれを使うことに感謝します。このタイプのタスクでは、私はむしろ 'template String;'を実行し、同時にvariadicテンプレートを学ぶでしょう:)(+1にもかかわらず) – sehe

+0

@sehe - それはパンで楽しくなるでしょう! – Nick

答えて

6

あなたは、0Substringを定義0し、任意のclass S:ここ

template <class S> 
struct Substring<0, 0, S> { 
    typedef Null substr; 
}; 

あなたは、ISubstringを定義LString< C, S >

template <int I, int L, char C, class S> 
struct Substring<I, L, String<C, S> > { 
    typedef typename Substring<I-1, L, S>::substr substr; 
}; 

誰もがより良い候補者ではありませんもう1つは、I, Lの方が良い一致ですが、String< C, S >。最初のケースを次のように宣言する場合:

template <char C, class S> 
struct Substring<0, 0, String< C, S > > { 
    typedef Null substr; 
}; 

これは他のものよりも専門的です。ただし、コードにはあいまいさがあります。

+0

それは(唯一の)問題でした。ありがとう。 – Nick