考虑以下程序:
struct A {
template <typename T>
operator T() { return T{}; }
};
int main() {
(void) A{}.operator int(); // (A)
(void) A{}.template operator int(); // (B)
}
(A) 被 GCC 和 Clang 接受,而 (B) 仅被 GCC 接受,但被 Clang 拒绝,并显示以下错误消息:
error: expected template name after 'template' keyword in nested name specifier
(void) A{}.template operator int(); // (B)
^~~~~~~~~~~~
事实上,(B) 应该是合法的,根据[临时名称]/5 https://timsong-cpp.github.io/cppwp/n4659/temp.names#5:
以关键字为前缀的名称template
应是一个模板 ID或者名称应引用类模板或别名模板。 [Note:关键词template
可能不适用于类模板的非模板成员。 —end note ] [ Note:正如情况一样typename
前缀,即template
prefix 在非绝对必要的情况下允许;即,当嵌套名称说明符或左边的表达式->
or .
不依赖于模板参数,或者使用不出现在模板的范围内。 —end note ]
并作为管辖的禁令[临时名称]/4 https://timsong-cpp.github.io/cppwp/n4659/temp.names#4不适用:
关键词template
据说出现在顶层合格的 ID如果它出现在 a 之外模板参数列表 or decl类型说明符。 [...]可选关键字 template
出现在顶层被忽略. [...]
并且最多仅声明应忽略该关键字(但不声明该程序格式错误)。
我没有找到任何条款[类.转换.fct] https://timsong-cpp.github.io/cppwp/n4659/class.conv.fct or [温度扣除转换] https://timsong-cpp.github.io/cppwp/n4659/temp.deduct.conv这与这个论点相冲突。
Question
- 对转换函数模板的显式访问添加前缀是否合法
template
关键词?
I have tested and repeated the compilers' behaviour above with various GCC and Clang versions for various language standard versions, but for the scope of this question, we may focus on GCC 10.1.0 and Clang 10.0.0 for -std=c++17
.