2017-01-12 100 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]

相關問題