考慮到以下代碼:
#include <type_traits>
struct outer {
struct inner {
unsigned int x = 0;
};
// static_assert(std::is_default_constructible<inner>:value,)
// "not default ctorable - inside");.
};
static_assert(std::is_default_constructible<out:inner>:value,
"not default ctorable - outside")。)
這個編譯正常。但是--如果我取消了outer里面的靜態斷言--兩個斷言在clang 和gcc 下都失敗了。為什么它們不能同時通過呢?
注意:
事實上,在第一個靜態斷言的地方,
inner類是完整的。該斷言并沒有因為不完整而失敗(這種失敗會產生關于不完整的具體錯誤資訊)。與相關的為什么我的類是非默認構造的?不同,這里沒有模板,所以不存在定義前的實體化。
如果你洗掉
x的初始化器并啟用斷言,代碼就可以編譯了。(這也與相關問題不同。)這一點:
#include <type_traits> struct outer { struct inner { unsigned int x = 0; }; 內部 get_an_inner() { static_assert(std::is_default_constructible<out::inner>:value, "not default ctorable - outside")。) return inner{}; } };編譯!
如果我們添加一個顯式的默認建構式,
constexpr inner() {}- 程式就會編譯。有一個LLVM 錯誤報告,基本上是關于同樣的事情,但它不僅僅是 clang,而且該錯誤報告也沒有得到任何評論。
更新:
- 已經提交了GCC bug 102199(針對 libstdc ).
- 已經評論了LLVM的錯誤,讓我們看看會發生什么。
uj5u.com熱心網友回復:
成員類的完備性狀態是復雜的。 因為他們的成員函式被允許對周圍的類范圍進行向前查找,在處理包含類的(其余部分)時,這些成員函式被視為尚未被定義,盡管事實上,最基本的完整性概念顯然是被滿足的:
struct A {
struct B {};
B b; // OK
};
在這一總體領域有各種公開的問題。例如,CWG2335和CWG1360。
uj5u.com熱心網友回復:
首先,為什么內部靜態斷言會導致外部靜態斷言失敗?這是因為模板只被實體化了一次。一旦std::is_default_constructible<inner>:value為false,它將保持false,即使default constructibility以某種方式改變。所以外層的 static_assert 并不是很有趣。為什么內部的 static_assert 會失敗呢?
為了理解這個問題,讓我們把它簡化到最低限度。沒有模板或標準庫!
struct outer {
struct inner {
unsigned int x = 0;
};
static constexpr inner i{};
};
這失敗了,出現了神秘的編譯器資訊。
$ g -c dc.cpp
dc.cpp:6:30: error: default成員初始化器for'outer::inner::x'在其包圍的class結束之前需要。
8 | static constexpr inner i{};
| ^
dc.cpp:3:24: note: defined here
5 | unsigned int x = 0;
| ^~~~
$ clang -c dc.cpp
dc.cpp:6:30: 錯誤。default成員初始化器for 'x'需要在成員函式之外的包圍class 'outer'的定義中出現
static constexpr inner i{};
^
dc.cpp:3:22: 注意:default成員初始化器在此宣告
unsigned int x = 0;
^
1 錯誤產生。
所以編譯器確實不能在需要的地方默認構建inner,但是為什么呢?
對錯誤資訊的文本進行快速搜索,可以得到這個。公認的答案將其歸類為 gcc 和 clang 的錯誤,但我并不相信。clang的bug報告說:"那么我們只會拒絕存在實際依賴回圈的情況",但是標準似乎并沒有在任何地方要求進行依賴回圈檢測。這可能是一個標準的缺陷,而不是一個編譯器的錯誤。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/314137.html
標籤:
上一篇:在編譯boost庫的'number_base.hpp'時,"這個庫現在需要一個C 11或更高版本的編譯器......"
下一篇:嘗試多載<<運算子時出錯
