'type_alias<char[N]>{}' VS 'char[N]{}' in function's arguments

`type_alias<char[N]>{}` VS `char[N]{}` in function's argument

本文关键字:char in function arguments VS type lt alias gt      更新时间:2023-10-16
  • 环境:x86-64Clang6.0.0

函数的定义:

void foo(const char*) {}
  1. foo(char[16]{}); //houston, there is a problem!
  2. foo(type_alias<char[16]>{}); //compile happily

type_alias很简单:

template<typename T>
using type_alias = T;

live demon


如注释所示,case 1无法编译,而case 2可以。

我知道alias declarationsusing不是文本替换(就像#define一样),它是类型的同义词。

但我仍然不知道如何解释这种情况。然后我给GCC一个try

prog.cc: In function 'int main()':
prog.cc:11:7: error: expected primary-expression before 'char'
foo(char[16]{});
^~~~
prog.cc:12:7: error: taking address of temporary array
foo(type_alias<char[16]>{});
^~~~~~~~~~~~~~~~~~~~~~

啊,GCC给了我一个错误!然后我用两个编译器的不同版本编译它:

  • Clang针对case 1的错误消息为:

程序cc:1:11:错误:函数样式强制转换或类型构造应为"(">

foo(char[16]{});
~~~~^
  • Clangcase 2通过。

  • GCC禁止这两种情况通过竞争。上面列出了case 1case 2的错误消息。

BTW,对于Clang,我也用pedantic-errors进行了测试,但没有任何变化。


问题:

  • 对于case 2:ClangGCC,谁符合标准?标准中有什么规范吗(语言律师)
  • 对于case 1:谁的错误消息更正确(IOW,符合标准)

更新

正如VTT所评论的,对于case 1,它应该是foo(const char[16]{});。为这个错误道歉。

但是Clang可以编译foo(type_alias<char[16]>{});。这好像是个虫子?

嗯,type_alias<cv T>{}等价于(cv T){},而不是cv T{}。当T是一个数组时,这种区别很重要:

foo((const char[16]){});              // OK
foo(type_alias<const char[16]>{});    // OK
foo(const type_alias<char>[16]{});    // KO
foo(const char[16]{});                // KO

演示:https://wandbox.org/permlink/KGf3HVqN3USq6yy8


对于案例2:Clang,GCC,谁符合标准?标准中有什么规范吗(语言律师)?

两者都接受foo(type_alias<char>[16]{}),但gcc会向发出警告(由于使用-Werror进行编译,因此此警告会变为错误;)。