8

我有以下代码(抱歉,代码块很大,但我无法再缩小范围了)

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 }; };

为什么这个类不会引起歧义,而其他类会引起歧义?对于具有真正 ::value 的类来说,这两者不是一回事吗?无论如何,任何关于我做错了什么的提示都值得赞赏。

感谢您的回答,我的真正问题(让编译器选择我的第一个专业化)通过替换struct Foo<X, Base<X>, void>似乎struct Foo<X, Base<X>, typename enable_if< Base<X> >::type >按我想要的方式工作来解决。

4

3 回答 3

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你替换你得到not ,即不进行处理。)YBase<X>whatever<Base<X> >::typevoid

如果你替换#2

template <typename X, typename Y>
struct Foo<X, Y, void > {};                        // #3

然后候选集再次包含两个模板,但是,#1 比 #3 更专业,因此被选中。

于 2009-07-22T19:31:16.287 回答
-1

你是不是错过了一个

<

象征 ?

于 2009-07-22T17:20:36.067 回答
-2

我认为您缺少“<”,模板应如下所示:

template< typename T >
struct myStruct
{};

//OR

template< class T >
struct myStruct
{};
于 2009-07-22T17:22:54.563 回答