303*_*303 3 c++ language-lawyer c++20
下面的代码符合C++20标准吗?或者,应该由于某些语法错误而被拒绝吗?所有 3 个编译器(Clang、GCC 和 MSVC)似乎都拒绝它。
template<typename...>
struct n {
template<typename>
struct b {
template<typename>
struct p {};
};
template<typename T>
struct d : b<T>::template p<T> {};
template<typename T>
d(b<int>::template p<T>) -> d<T>;
template<typename T>
static constexpr auto v = d{b<int>::template p<T>{}};
};
inline constexpr auto w = n{}.v<int>;
Run Code Online (Sandbox Code Playgroud)
当删除 type 的模板头时n,所有编译器都会接受该代码。为什么这很重要?标准对基于是否模板化的代码处理方式有何规定n?
Clang 的错误消息:
<source>:11:15: error: 'template' keyword not permitted here
11 | d(b<int>::template p<T>) -> d<T>;
| ^~~~~~~~
<source>:11:24: error: member 'p' declared as a template
10 | template<typename T>
| ~~~~~~~~~~~~~~~~~~~~
11 | d(b<int>::template p<T>) -> d<T>;
| ^
<source>:11:29: error: expected ';' at end of declaration list
11 | d(b<int>::template p<T>) -> d<T>;
| ^
| ;
<source>:13:54: error: expected '}'
13 | static constexpr auto v = d{b<int>::template p<T>{}};
| ^
<source>:13:32: note: to match this '{'
13 | static constexpr auto v = d{b<int>::template p<T>{}};
| ^
<source>:13:27: error: declaration of variable 'v' with deduced type
'const auto' requires an initializer
13 | static constexpr auto v = d{b<int>::template p<T>{}};
| ^
<source>:13:27: error: declaration of variable 'v' with deduced type
'const auto' requires an initializer
<source>:15:31: note: in instantiation of static data member 'n<>::v<int>'
requested here
15 | inline constexpr auto w = n{}.v<int>;
| ^
<source>:15:23: error: constexpr variable 'w' must be initialized by a
constant expression
15 | inline constexpr auto w = n{}.v<int>;
| ^ ~~~~~~~~~~
<source>:15:27: note: non-literal type 'auto' cannot be used in a constant
expression
15 | inline constexpr auto w = n{}.v<int>;
| ^
Run Code Online (Sandbox Code Playgroud)
GCC的错误信息:
<source>:13:32: error: missing template arguments before '{' token
13 | static constexpr auto v = d{b<int>::template p<T>{}};
| ^
<source>:15:31: error: 'struct n<>' has no member named 'v'
15 | inline constexpr auto w = n{}.v<int>;
| ^
<source>:15:33: error: expected primary-expression before 'int'
15 | inline constexpr auto w = n{}.v<int>;
| ^~~
Run Code Online (Sandbox Code Playgroud)
MSVC的错误信息:
<source>(13): error C2760: syntax error: '{' was unexpected here; expected '}'
<source>(13): note: the template instantiation context (the oldest one first) is
<source>(14): note: see reference to class template instantiation
'n<<unnamed-symbol>...>' being compiled
Run Code Online (Sandbox Code Playgroud)
正如HolyBlackCat提到的,添加typename到使得在GCC和MSVC上b<int>::template p<T>{}的构建成为可能。d然而,Clang 仍然拒绝该代码,因为它似乎与推导指南存在问题。
这给我留下了一个问题:是否 typename可以从d的推导指南中省略,同时仍然符合 C++20 标准。MSVC 还允许省略typename何时将大括号更改为括号,但我认为这种行为是不合规的。
我认为语言律师没有必要这样做,有一个简单的解释。
b<int>是一个依赖类型,它依赖于 的模板参数n。
您可能会问,它是如何依赖的?因为它可以专门化,例如:
template <>
template <>
struct n<int>::b<long> {};
Run Code Online (Sandbox Code Playgroud)
如果您在 前面加上typename,b<int>则代码可以工作......但 Clang 不喜欢推导指南,这可能应该是一个单独的问题。
<source>:11:5: error: deduction guide template contains a template parameter that cannot be deduced
11 | d(typename b<int>::template p<T>) -> d<T>;
| ^
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
84 次 |
| 最近记录: |