c++ - constexpr 函数允许什么?

标签 c++ function c++14 constexpr c++17

constexpr functions不应包含:

A definition of a variable of non-literal type

但是在这个答案中,一个 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;
    }();
}

在我的评论中,我在其中定义了一个 div_t:How can I Initialize a div_t Object?

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;
}

禁止“定义非字面量类型的变量”到底是什么意思?

Visual Studio 2015 不允许我定义 div_t,但我发现允许将此类非法行为包装在 lambda 中并执行它是荒谬的。我想知道哪个编译器在 div_t 定义方面的行为是否正确。

最佳答案

几乎可以保证,如果存在差异,gcc 的行为是正确的,因为 Visual Studio 2015 不支持 constexpr 的扩展:https://msdn.microsoft.com/en-us/library/hh567368.aspx#C-14-Core-Language-Features

C++11 constexpr 函数

函数体只能包含:

  • null statements (plain semicolons)
  • static_assert declarations
  • typedef declarations and alias declarations that do not define classes or enumerations
  • using declarations
  • using directives
  • exactly one return statement

所以 不能容忍 decltype(div(T{}, T{})) x{} 的定义。然而,滚动建议的三元组是可以接受的 hereconstexpr 函数中实现相同的结果:

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};
}

Live Example

C++14 constexpr 函数

函数体可以包含之外的任何内容:

  • an asm declaration
  • a goto statement
  • a statement with a label other than case and default
  • a try-block
  • a definition of a variable of non-literal type
  • a definition of a variable of static or thread storage duration
  • a definition of a variable for which no initialization is performed

定义“文字类型”的位置 here ,虽然特别针对对象,但它们可能是具有普通析构函数的聚合类型。所以 div_t 绝对符合条件。因此 ,并且通过扩展 gcc,可以容忍 decltype(div(T{}, T{})) x{} 的定义。

C++17 constexpr 函数

C++17 在“文字类型”的定义中增加了对闭包类型的支持,所以我觉得奇怪的是 gcc 和 Visual Studio 都支持在 return 语句中使用 lambda。我想这要么是前瞻性支持,要么是编译器选择内联 lambda。无论哪种情况,我都不认为它符合 的条件。 constexpr 函数。

[ Source ]

关于c++ - constexpr 函数允许什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41618576/

相关文章:

c - 如何将用户输入函数与另一个函数一起使用?

javascript - 将 javascript 对象作为参数传递给函数 - typescript 等效

c++ - 如何捕捉函数调用

c++ - vector 析取

c++ - 直接从 C++ 调用 D 函数

c++ - 为什么初始化列表允许在 C++ 中缩小类型?

c++ - 解决 GCC 5.5 unordered_map 错误

c - 尝试从另一个包含结构的函数调用一个函数

c++ - 部分模板模板 vector 特化

c++ - Boost Geometry:计算 vector 差