【问题标题】:What "conversion" of template template parameters is allowed in C++?C++ 中允许对模板模板参数进行哪些“转换”?
【发布时间】:2021-07-18 04:33:03
【问题描述】:

我试图了解在什么情况下可以将类型模板作为参数传递给具有不同签名的模板模板参数。例如,我希望以下内容可能会成功编译。

template <typename...>
struct foo { };

template <template <typename> typename Template>
struct bar { };

using quux = bar<foo>;

毕竟,bar 要求的是一个模板,它愿意只接受一种类型的模板参数,而我给了它一个。但是对于 Clang 11.0.1,这不会编译。

好的,好的。当然,如果不允许这样做,那么以下内容也应该被禁止。

template <typename>
struct foo { };

template <template <typename...> typename Template>
struct bar { };

using quux = bar<foo>;

这里bar 要求提供一个可以接受任意数量的类型模板参数的模板,而我不会 给它一个。然而 Clang 接受了这一点! (当然,如果我在 bar 内编写代码,使用与 foo 的签名不匹配的模板参数实例化 Template,它仍然会失败。)

这对我来说似乎倒退了。它允许将更具体的模板签名转换为更通用的模板签名,而不是相反。

我也尝试使用 GCC 10.2.0。 GCC 两者都接受。哈哈。

我正在使用-Wall -Wextra -O0 -std=c++20 -pedantic 与两个编译器一起编译。

标准是否真的没有说明上面的第一个示例是否格式错误,或者至少有一个编译器不符合标准?

而且,不管标准要求什么,为什么 Clang 会在这里做出选择?对我来说这似乎是一个错误。

【问题讨论】:

  • 这是一份缺陷报告 IIRC,但我不记得分辨率。我认为 Clang的行为符合标准。
  • Clang 没有问题。很小心。使用-frelaxed-template-template-args

标签: c++ g++ language-lawyer clang++ template-templates


【解决方案1】:

我认为 Clang 是错误的。由于 C++17(P0522R0CWG 150),模板采用像 foo 这样的参数包,应该允许将 template template argument 指定为 bar,即使它需要一个模板参数。

template<class T> class A { /* ... */ };
template<class T, class U = T> class B { /* ... */ };
template <class ...Types> class C { /* ... */ };

template<template<class> class P> class X { /* ... */ };
X<A> xa; // OK
X<B> xb; // OK in C++17 after CWG 150
         // Error earlier: not an exact match
X<C> xc; // OK in C++17 after CWG 150
         // Error earlier: not an exact match

【讨论】:

    猜你喜欢
    • 2013-09-15
    • 1970-01-01
    • 2010-09-17
    • 2015-02-20
    • 1970-01-01
    • 2017-12-30
    • 2017-06-22
    相关资源
    最近更新 更多