2017-01-12 178 views
7

constexpr functions不应该包含:在constexpr函数中允许什么?

非文字类型

但在此答案的λ是一个所定义的变量的定义: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定义方面表现正确。

+2

什么版本的C++语言?这些要求比2011年有所放松。 – rubenvb

+0

@rubenvb好的问题,我编辑过。但是C++ 14。 –

+4

lambda表达式是一个表达式,而不是一个变量定义。但是在C++ 17之前,lambda表达式不能出现在[常量表达式](http://en.cppreference.com/w/cpp/language/constant_expression)中。事实上,[当上下文需要不断表达时,MSVC会抱怨](http://rextester.com/ZBRLBR12534)。 – cpplearner

回答

8

它几乎可以肯定,如果有差异GCC有正确的行为,原因是Visual Studio 2015年不支持的扩展constexprhttps://msdn.microsoft.com/en-us/library/hh567368.aspx#C-14-Core-Language-Features

C++ 11 constexpr功能

功能体可以只包含

  • 空语句(纯分号)
  • static_assert声明
  • typedef声明和别名声明没有定义的类或枚举
  • using声明
  • using指令
  • 只有一个return声明

所以无法容忍的定义。然而,可以接受的滚动三元建议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功能

函数体可以含有任何但是

  • 的asm声明
  • goto语句
  • 比情况和违约等标签的声明
  • try块
  • 非文字类
  • 的定义的变量的定义静态或线程存储时限
  • 为不进行初始化的变量的定义的可变

其中“文字类型”定义为here,专门用于对象,但它们可能是具有简单析构函数的聚合类型。所以div_t绝对有资格。因此和扩展gcc可以容忍decltype(div(T{}, T{})) x{}的定义。

C++ 17个constexpr功能

C++ 17增加了封闭类型的“文本类型”,所以我觉得奇怪的是GCC和Visual Studio支持在使用拉姆达的高清支持return声明。我想这是向前看的支持或编译器选择内联lambda。在任何一种情况下,我都认为它不符合constexpr函数的要求。

[Source]

相关问题