可变参数模板的部分特化

发布于 2024-12-19 17:25:12 字数 1856 浏览 2 评论 0原文

考虑以下类模板“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是模棱两可的。因为:

很明显#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'作为形参模板进行模板实参推导。假设唯一的参数类型是X,推导的T1是A1,并且Types为空。

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

第二步是使用 #3' 作为参数模板和 #2' 作为参数模板来完成。给定唯一的参数类型是 X,根据 14.8.2.5/9(注意这一段是 N3281 最近修改的),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.0 选择#2。然而,这些编译器非常不可靠,以至于它们不遵循 N3281 的其他更改。

Consider the following class template 'X' and its partial specializations.

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 ?

I suspect X<int> is ambiguous. It is because:

It is obvious that both #2 and #3 are more specialized than #1, #2 and #3 are now compared. According to 14.5.5.2, let's consider which of the following #2' and #3' is more specialized.

template <class T1>
void f(X<T1>);             // #2'

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

According to 14.8.2.4, the first step is the template argument deduction using #2' as the argument template and #3' as the parameter template. Given the only argument type is X<A1>, the deduced T1 is A1, and Types is empty.

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

The second step is done using #3' as the argument template and #2' as the parameter template. Given the only argument type is X<A1, Args...>, according to 14.8.2.5/9 (note that this paragraph is recently revised by N3281), Args is simply ignored, the deduced T1 is A1 and argument deduction succeeds.

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

Finally, the bidirectional argument deductions succeeded. So #2 is just as specialized as #3. In conclusion, X<int> is ambiguous.

My question is: "is my interpretation correct?"

If this interpretation is correct, the definition of 'std::common_type' in 20.9.7.6/3 is inappropriate.

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

When common_type<A, B> is used, #3 and #4 are ambiguous.

Note: on the first example, GCC 4.7.0 (snapshot) and Clang 3.0 select #2. However, these compilers are so unreliable that they don't follow the other changes by N3281.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

葬花如无物 2024-12-26 17:25:12

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

在大多数情况下,所有模板参数都必须具有值才能
推导成功,但出于部分排序的目的,模板
参数可以保留没有值,只要它没有在
用于部分排序的类型。 [ 注意:模板参数
在非推导上下文中使用的内容被视为已使用。 ——尾注] [
示例:

模板  T f(int); // #1
模板 Tf(U); // #2
无效 g() {
fint(1); // 调用#1
}

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

14.8.2.4, section 11 (I refer to draft N3242).

In most cases, all template parameters must have values in order for
deduction to succeed, but for partial ordering purposes a template
parameter may remain without a value provided it is not used in the
types being used for partial ordering. [ Note: A template parameter
used in a non-deduced context is considered used. —end note ] [
Example:

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

In your case, #3 will be used.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文