我有以下代码(对于大代码块很抱歉,但我不能再缩小它了)
template <bool B>
struct enable_if_c {
typedef void type;
};
template <>
struct enable_if_c<false> {};
template <class Cond>
struct enable_if : public enable_if_c<Cond::value> {};
template <typename X>
struct Base { enum { value = 1 }; };
template <typename X, typename Y=Base<X>, typename Z=void>
struct Foo;
template <typename X>
struct Foo<X, Base<X>, void> { enum { value = 0 }; };
template <typename X, typename Y>
struct Foo<X, Y, typename enable_if<Y>::type > { enum { value = 1 }; };
int main(int, char**) {
Foo<int> foo;
}
但是无法使用gcc(v4.3)和
进行编译foo.cc: In function ‘int main(int, char**)’:
foo.cc:33: error: ambiguous class template instantiation for ‘struct Foo<int, Base<int>, void>’
foo.cc:24: error: candidates are: struct Foo<X, Base<X>, void>
foo.cc:27: error: struct Foo<X, Y, typename enable_if<Y>::type>
foo.cc:33: error: aggregate ‘Foo<int, Base<int>, void> foo’ has incomplete type and cannot be defined
好的,所以这是不明确的。但我并不认为这是一个问题,因为在使用专业化时,它几乎总是会有些含糊不清。但是,只有在使用enable_if<...>
的类时才会触发此错误,如果我将其替换为类似以下的类则没有问题。
template <typename X, typename Y>
struct Foo<X, Y, void > { enum { value = 2 }; };
为什么这个课程不会引起歧义,而其他人呢?具有true :: value的类不是两个相同的东西吗? 无论如何,任何关于我做错的提示都会受到赞赏。
感谢您的回答,我的真正问题(让编译器选择我的第一个专业化)通过将struct Foo<X, Base<X>, void>
替换为struct Foo<X, Base<X>, typename enable_if< Base<X> >::type >
来解决,这似乎是有效的我想要。
答案 0 :(得分:12)
你的问题的主旨是:
template <typename X, typename Y, typename Z>
struct Foo {};
template <typename X>
struct Foo<X, Base<X>, void> {}; // #1
template <typename X, typename Y>
struct Foo<X, Y, typename whatever<Y>::type> {}; // #2
并且您正在尝试将其与
相匹配Foo<int, Base<int>, void>
显然,两个专业都匹配(第一个与X = int
匹配,第二个与X = int, Y = Base<int>
匹配。
根据标准第14.5.4节,如果有更多匹配的特化,则构造它们之间的部分排序(如14.5.5.2中所定义),并使用最专业的一个。然而,在你的情况下,没有一个比另一个更专业。 (简单地说,一个模板比另一个模板更专业,如果你可以用某种类型替换后一个模板的每个类型参数,结果得到前者的签名。另外,如果你有whatever<Y>::type
并且你替换{ {1}}使用Y
Base<X>
而不是whatever<Base<X> >::type
,即没有执行处理。)
如果用
替换void
#2
然后候选集再次包含两个模板,但是,#1比#3更专业,因此被选中。
答案 1 :(得分:-1)
你错过了
<
符号?
答案 2 :(得分:-2)
我认为你错过了一个'&lt;',模板应该是这样的:
template< typename T >
struct myStruct
{};
//OR
template< class T >
struct myStruct
{};