[英]Constexpr compound assignment operator in clang and gcc
我有以下代碼:
main.cpp中
#include <cstdint>
#include <type_traits>
enum class FooEnum : uint8_t{
Foo1 = 0,
Foo2 = 1
};
constexpr uint32_t& operator|= (uint32_t& lhs, FooEnum rhs) {
return lhs |= 1u << static_cast<uint8_t>(rhs);
}
int main() {
uint32_t bar{0};
bar|=FooEnum::Foo1;
}
基本上, |=
運算符應該采用枚舉並設置位,其位置對應於其整數值。
在fedora 21上用clang ++ 3.5.0編譯時,一切正常,但是當用g ++ 4.9.2編譯時,它會拋出一個錯誤,說這不是一個常量表達式 :
main.cpp: In function ‘constexpr uint32_t& operator|=(uint32_t&, FooEnum)’:
main.cpp:16:2: error: expression ‘(lhs = (lhs | (1u << ((int)rhs))))’ is not a constant-expression
}
^
這適用於所有類型的編譯器標志組合,但您可以使用g++ -std=c++11 -o a.out main.cpp
(c ++ 14沒有區別)
所以我的問題是:
operator|=
這樣g ++會接受它作為constexpr
? 編輯:
如果您想知道,為什么我首先嘗試將運算符聲明為constexpr
,盡管在示例中不需要:
在我的實際代碼中,我使用|=
-operator來實現(constexpr) |
-operator,我想在constexpr表達式中使用,但在此之前,我偶然發現了兩個編譯器之間的區別,沒有意識到,gcc4.9並不完全支持c ++ 14(但是接受-std=c++14
flag)。
當使用運算符實際初始化一個全局constexpr變量時,即使clang只用c ++ 14標志編譯它。
表達式lhs |= 1u << static_cast<uint8_t>(rhs)
本身永遠不能是一個常量表達式 ,因為它修改了lhs
。 禁止在C ++ 14中使用的規則是§5.19/ 2.15(在C ++ 11中也存在有效的等效規則):
條件表達式
e
是核心常量表達式,除非根據抽象機器(1.9)的規則評估e
將評估以下表達式之一:
- 修改對象(5.17,5.2.6,5.3.2), 除非它應用於文字類型的非易失性左值,該文字類型引用一個非易失性對象,其生命周期始於
e
的評估范圍內 ;
在C ++ 11中,由於§7.1.5/ 5,它必須是一個:
對於
constexpr
函數,如果不存在函數參數值,使得函數調用替換將產生常量表達式(5.19),則程序格式錯誤; 無需診斷。
在調用替換之后,不存在使返回的表達式成為常量表達式的參數:賦值可以防止這種情況發生。 因此,程序在C ++ 11中-std=c++11
不正確(但不需要診斷),並且在使用-std=c++11
編譯時,GCC顯示符合規范的行為。
在C ++ 14中,該規則已經過調整:
對於非模板,非默認的
constexpr
函數[...],如果不存在參數值,使得函數[...]的調用可以是核心常量表達式(5.19)的計算子表達式 ,則程序格式錯誤; 無需診斷。
這使得返回表達式本身成為非常量表達式,只要該函數可以在另一個核心常量表達式中進行求值,例如從另一個constexpr
函數中:
constexpr auto foo(FooEnum rhs)
{
uint32_t x = 0;
x |= rhs;
return x;
}
foo(FooEnum::Foo1)
是核心常量表達式,因此可以在核心常量表達式中調用operator|=
,因此函數定義格式正確。
正如評論中的@dyp所述,GCC僅支持自版本5以來的“對constexpr函數的放寬約束”特性.GCC 5.1編譯代碼 。
所以現在constexpr
函數的主體通常由不是常量表達式的語句組成。 第一個引用部分之后的示例顯示了一個函數incr
,GCC也會拒絕該函數:
constexpr int incr(int &n) { return ++n; } constexpr int h(int k) { int x = incr(k); // OK: incr(k) is not required to be a core // constant expression return x; }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.