![](/img/trans.png)
[英]Why does GCC -O3 cause infinite std::distance with filter iterators over a std::deque?
[英]Why does std::visit in an unsatisfied concept cause a compile error in gcc
這段代碼:
#include <concepts>
#include <string>
#include <variant>
struct any_callable {
public:
template<typename T>
void operator()(T&&) {}
};
template<typename V>
concept is_variant = requires(V v) { std::visit(any_callable{}, v); };
int main() {
constexpr bool wrapped = is_variant<std::string>;
}
不能在 gcc 11 下編譯。它給出了一堆關於valueless_by_exception
等的錯誤。 但是,它確實在 msvc ( Godbolt ) 下編譯。 現在,據我所知,在這種情況下,如果它通常無法編譯,它將衰減為 false,否則為 true。 msvc 的行為似乎支持這一點。
所以:這是 gcc 中的錯誤,msvc 的非標准功能,和/或我的代碼有錯嗎?
那個:
template<typename V>
concept is_variant = requires(V v) { std::visit(any_callable{}, v); };
完全有效是最近的變化,這是P2162的結果。 為了使此檢查工作,您需要std::visit
成為通常所說的“SFINAE-friendly”。 也就是說:它必須以某種方式被限制在“變體”上,這樣如果V
是變體,它就可以工作,如果V
不是變體,那么visit
從重載集中刪除,這樣這個調用就是一個無效的表達式(以便可以拒絕該concept
)。
但是,在 P2162 之前, std::visit
沒有約束。 這不是 SFINAE 友好的:調用要么有效,要么格式錯誤。 正是這篇論文添加了一個約束,即您傳遞給它的類型是變體(或從一個變體)。 這就是為什么您會看到您所看到的錯誤: visit
調用失敗,但不是以對concept
檢查友好的方式。
在 P2162 之后(正如論文所指出的,MSVC 已經實現,但 libstdc++ 沒有實現),您的支票將有效。
但是我們可以在 C++20 中更容易地做到這一點,而無需進入變體機制 - 通過以與論文相同的方式直接檢查變體性:
template<typename V>
concept is_variant = requires(V v) {
[]<typename... Ts>(std::variant<Ts...> const&){}(v);
};
如果v
是一個variant
或者它繼承自一個variant
,那么該 lambda 可以用v
調用。 否則,它是錯誤的。 這比通過visit
更直接。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.