我不明白为什么这段代码会在没有错误的情况下编译:
#include <iostream>
template <class T>
struct Test
{
static constexpr T f() {return T();}
};
int main()
{
Test<void> test;
test.f(); // Why not an error?
return 0;
}
根据标准是否可以,还是编译容差?
答案 0 :(得分:25)
这看起来有效draft C++11 standard,如果我们看一下5.2.3
明确的类型转换(功能表示法)段 2 说(< em>强调我的):
表达式T(),其中T是简单类型说明符或 typename-specifier用于非数组完整对象类型或 (可能是cv-qualified)void type ,创建一个prvalue 指定的类型,其值是由值初始化生成的 (8.5)T型物体;没有为void()做初始化 情况下。[...]
措辞非常相似pre C++11。
这在 constexpr 中没问题,即使7.1.5
段3
段说:
constexpr函数的定义应满足以下条件 约束:
并包含此子弹:
其返回类型应为文字类型;
和 void 不是 C ++ 11 中的文字,按照3.9
段 10 ,但如果我们再查看段落 6 ,它会给出一个符合这种情况的异常,它说:
如果实例化了constexpr函数的模板特化 类模板的模板或成员函数将无法满足 constexpr函数或constexpr构造函数的要求, 该专业化不是constexpr功能或constexpr 构造函数。 [注意:如果该函数是一个成员函数,它会 仍然是如下所述的const。 -end note] 如果没有专业化 模板将产生constexpr函数或constexpr 构造函数,该程序是不正确的;无需诊断。
由于noted void 中的Casey C++14 draft standard是文字,因此这是3.9
类型段 10 说:
类型是文字类型,如果它是:
并包括:
- 无效;或
答案 1 :(得分:6)
请参阅@Shafik Yaghmour的答案以获取完整信息。
以下段落禁止非模板(7.1.5(3)):
constexpr
函数的定义应满足以下约束条件:
[...]
其返回类型应为文字类型或对文字类型的引用
详细说明,文字类型在3.9(10)中定义为标量类型或数组或结构中文字类型对象的组合。 void
不是3.9(9)的标量类型。
答案 2 :(得分:1)
您的函数返回void()
的值,您不是从void函数本身返回。您将返回NULL
值。你在做什么等同于:
void f() { return void(); }
返回void值,唯一的void值。你不能从void函数返回任何其他东西,因为它将是一个不同的类型。