可变参数模板的部分专业化

考虑以下类模板“X”及其部分专业化。

template <class ...Types> struct X {}; // #1 template <class T1> struct X<T1> {}; // #2 template <class T1, class ...Types> struct X<T1, Types...> {}; // #3 X<int> x; // #2 or #3 ? 

我怀疑X <int>是不明确的。 这是因为:

很明显,#2和#3比现在比较#1,#2和#3更专业。 根据14.5.5.2,让我们考虑以下#2和#3中哪一个更专业。

 template <class T1> void f(X<T1>); // #2' template <class T1, class ...Types> void f(X<T1, Types...>); // #3' 

根据14.8.2.4,第一步是使用#2'作为参数模板,#3'作为参数模板的模板参数推导。 给定唯一的参数types是X <A1>,推导出的T1是A1,types是空的。

 A = X<A1>, P = X<T1, Types...> => T1 = A1, Types = {} 

第二步是使用#3作为参数模板,使用#2作为参数模板。 根据14.8.2.5/9(请注意,本段最近由N3281修改)给出了唯一的参数types是X <A1,Args …>,简单地忽略了Args,推导出的T1是A1,参数推导成功。

 A = X<A1, Args...>, P = X<T1> => T1 = A1 (Args is ignored) 

最后,双向论证扣除成功。 所以#2和#3一样专业。 总之,X <int>是不明确的。

我的问题是:“我的解释是否正确?”

如果这个解释是正确的,那么20.9.7.6/3中“std :: common_type”的定义是不合适的。

 template <class ...T> struct common_type; // #1 template <class T> struct common_type<T> // #2 { typedef T type; }; template <class T, class U> struct common_type<T, U> // #3 { typedef decltype(true ? declval<T>() : declval<U>()) type; }; template <class T, class U, class ...V> struct common_type<T, U, V...> // #4 { typedef typename common_type<typename common_type<T, U>::type, V...>::type type; }; 

当使用common_type <A,B>时,#3和#4是不明确的。

注意:在第一个例子中,GCC 4.7.0(快照)和Clang 3.0select#2。 但是,这些编译器是不可靠的,他们不遵循N3281的其他变化。

14.8.2.4,第11节(我参考N3242草案)。

在大多数情况下,所有的模板参数都必须有值才能成功扣除,但是对于部分sorting而言,如果模板参数没有用于部分sorting的types,可能会保留一个值。 [注意:在非推导的上下文中使用的模板参数被认为是被使用的。 – 结束] [例子:

 template <class T> T f(int); // #1 template <class T, class U> T f(U); // #2 void g() { f<int>(1); // calls #1 } 

在你的情况下,#3将被使用。