2

所以我剛剛開始與模板元編程,我一直在寫一個字符串類。我實現了ToString,Concat,CharAt和Length,沒有太多與模板相關的問題。我試圖實現子串如下:C++模板Metaprogramming專業化歧義

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;'同時學習可變參數模板:)(+1但是) – sehe

+0

@sehe - 它會在包子上變得有趣! – Nick

回答

6

在這裏定義一個Substring00任何class S

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

在這裏定義一個SubstringILString< 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; 
}; 

沒有一個是更好的人選比其他,因爲一個更好的匹配I, L,但更糟糕的匹配String< C, S >。如果您要將第一種情況聲明爲:

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

然後這將比其他任何更專門。但是,您的代碼中可能存在其他不明確的來源。

+0

這是(唯一的)問題。謝謝。 – Nick