以下代码compiles successfully both with clang++ 3.8.0 and g++ 7.2.0(编译标志为-std=c++14 -O0 -Wall -Wextra -Werror -pedantic-errors
):
#include <iostream>
int foo_int(int)
{
std::cout << "int foo(int)" << std::endl;
return 0;
}
void foo_void(int)
{
std::cout << "void foo(int)" << std::endl;
}
auto foo_auto_int(int)
{
std::cout << "auto foo(int), auto == int" << std::endl;
return 0;
}
auto foo_auto_void(int)
{
std::cout << "auto foo(int), auto == void" << std::endl;
return void();
}
int main()
{
auto (*fi)(int) = foo_int;
auto (*fv)(int) = foo_void;
auto (*fai)(int) = foo_auto_int;
auto (*fav)(int) = foo_auto_void;
(void)fi(0);
fv(0);
(void)fai(0);
fav(0);
}
它是一个有效的C ++代码吗?
请注意,decltype(auto)
为rejected both by clang++ and g++ in the same situation。
答案 0 :(得分:10)
编译器表现正常。
auto
和decltype(auto)
类型说明符用于指定占位符类型,稍后将通过从初始化程序中扣除来替换它。[...]
auto
或decltype(auto)
将在 decl-specifier-seq 和 decl中显示为 decl-specifiers 之一-specifier-seq 后面应跟着一个或多个声明符,每个声明符后面都应跟一个非空初始值设定项。
这说auto
和decltype(auto)
只能用您在声明(static
,virtual
等)前面写的说明符编写,其类型使用初始值设定项从紧随其后的声明符中推断出来。
auto
auto (*fi)(int) = foo_int;
案例中的声明符为(*fi)(int)
,格式为
( ptr-operator declarator-id ) ( parameter-declaration-clause )
因此,auto (*fi)(int) = foo_int;
是有效的,只要它deduction succeeds。同样对其他几个人来说。
decltype(auto)
从[dcl.spec.auto.deduct]开始,给定包含占位符类型的类型T
如果占位符是
decltype(auto)
类型说明符,则T
应仅为占位符。
这意味着添加任何其他内容都是非法的
int i;
decltype(auto)* p = &i; // error, declared type is not plain decltype(auto)
因此decltype(auto) (*fi)(int) = foo_int;
是非法的。