constexpr
functions不应包含:
非文字类型
变量的定义
但在这个答案中,lambda定义在一个:https://stackoverflow.com/a/41616651/2642059
template <typename T>
constexpr auto make_div(const T quot, const T rem)
{
return [&]() {
decltype(std::div(quot, rem)) result;
result.quot = quot;
result.rem = rem;
return result;
}();
}
在我的评论中,我在一个How can I Initialize a div_t Object?
中定义了div_t
template <typename T>
constexpr decltype(div(T{}, T{})) make_div(const T quot, const T rem)
{
decltype(div(T{}, T{})) x{};
x.quot = quot;
x.rem = rem;
return x;
}
禁止对非文字类型的变量进行定义&#34;究竟是什么意思?
Visual Studio 2015不允许我对div_t
的定义,但我发现在lambda中包含这些非法行为并执行它是不允许的。我想知道哪一个编译器在div_t
定义方面表现正常。
答案 0 :(得分:15)
几乎可以保证,如果存在差异,gcc具有正确的行为,因为Visual Studio 2015不支持constexpr
的{{1}}扩展:c++14
constexpr
函数函数体只能 包含:
- null语句(普通分号)
static_assert
声明typedef
声明和不定义类或枚举的别名声明using
声明using
指令- 恰好一个
return
声明
因此https://msdn.microsoft.com/en-us/library/hh567368.aspx#C-14-Core-Language-Features无法容忍decltype(div(T{}, T{})) x{}
的定义。然而,在constexpr
函数中推荐三元建议c++11以获得相同的结果是可以接受的:
template <typename T>
constexpr auto make_div(const T quot, const T rem)
{
using foo = decltype(div(T{}, T{}));
return foo{1, 0}.quot != 0 ? foo{quot, rem} : foo{rem, quot};
}
constexpr
函数函数体可能包含除之外的任何内容:
- asm声明
- 一个转到声明
- 带有除case和default之外的标签的声明
- 试用块
- 非文字类型变量的定义
- 静态或线程存储持续时间变量的定义
- 未执行初始化的变量的定义
如果定义了“文字类型”Live Example,特别是对于对象,它们可能是具有普通析构函数的聚合类型。所以div_t
绝对有资格。因此,here和扩展名gcc可以容忍decltype(div(T{}, T{})) x{}
的定义。
constexpr
函数 C ++ 17在“Literal Type”的定义中添加了对闭包类型的支持,所以我觉得奇怪的是gcc和Visual Studio都支持在return
语句中使用lambda。我想这是前瞻性支持或编译器选择内联lambda。在任何一种情况下,我认为它不符合c++14 constexpr
函数。
[c++14]