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