简体   繁体   English

为什么std::visit in a unsatisfied concept会导致gcc编译错误

[英]Why does std::visit in an unsatisfied concept cause a compile error in gcc

This code:这段代码:

#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>;
}

does not compile under gcc 11. It gives a bunch of errors about valueless_by_exception and such.不能在 gcc 11 下编译。它给出了一堆关于valueless_by_exception等的错误。 It does, however, compile under msvc ( godbolt ).但是,它确实在 msvc ( Godbolt ) 下编译。 Now as I understand concepts, in this instance, if it would usually fail to compile it will decay to false, otherwise to true.现在,据我所知,在这种情况下,如果它通常无法编译,它将衰减为 false,否则为 true。 The behaviour of msvc would seem to support this. msvc 的行为似乎支持这一点。

So: Is this a bug in gcc, a non-standard feature of msvc, and/or is my code wrong?所以:这是 gcc 中的错误,msvc 的非标准功能,和/或我的代码有错吗?

That this:那个:

template<typename V>
concept is_variant = requires(V v) { std::visit(any_callable{}, v); };

works at all is a very recent change, a result of P2162 .完全有效是最近的变化,这是P2162的结果。 In order for this check to work, you need std::visit to be what's usually referred to as "SFINAE-friendly".为了使此检查工作,您需要std::visit成为通常所说的“SFINAE-friendly”。 That is: it must somehow be constrained on "variant-ness" such that if V is a variant, it works, and if V is not a variant, then visit is removed from the overload set such that this call is an invalid expression (so that the concept can be rejected).也就是说:它必须以某种方式被限制在“变体”上,这样如果V是变体,它就可以工作,如果V不是变体,那么visit从重载集中删除,这样这个调用就是一个无效的表达式(以便可以拒绝该concept )。

However, prior to P2162, there were no Constraints on std::visit .但是,在 P2162 之前, std::visit没有约束 It was not SFINAE-friendly: the call would either work or be ill-formed.这不是 SFINAE 友好的:调用要么有效,要么格式错误。 It was this paper that added the constraint that the types that you're passing into it are variants (or inherit from one).正是这篇论文添加了一个约束,即您传递给它的类型是变体(或从一个变体)。 That's why you're seeing the error you're seeing: the call to visit was failing, but not in a way that was friendly to the concept check.这就是为什么您会看到您所看到的错误: visit调用失败,但不是以对concept检查友好的方式。

Post-P2162 (which, as the paper points out, MSVC already implemented, but libstdc++ did not), your check will be valid.在 P2162 之后(正如论文所指出的,MSVC 已经实现,但 libstdc++ 没有实现),您的支票将有效。

But we can do this easier in C++20 without having to go into the variant machinery - by checking the variant-ness directly in the same way that the paper does it:但是我们可以在 C++20 中更容易地做到这一点,而无需进入变体机制 - 通过以与论文相同的方式直接检查变体性:

template<typename V>
concept is_variant = requires(V v) {
    []<typename... Ts>(std::variant<Ts...> const&){}(v);
};

That lambda is invocable with v if either v is a variant or it inherits from one.如果v是一个variant或者它继承自一个variant ,那么该 lambda 可以用v调用。 Otherwise, it's ill-formed.否则,它是错误的。 This is more straight-forward than going through visit .这比通过visit更直接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么GCC -O3与std :: deque上的过滤器迭代器导致无限的std :: distance? - Why does GCC -O3 cause infinite std::distance with filter iterators over a std::deque? 为什么std :: condition_variable作为类成员会导致std :: thread发生编译错误? - Why does std::condition_variable as a class member cause compile errors with std::thread? 静态成员变量的概念检查在gcc上编译错误 - Concept checking of static member variables compile error on gcc std::vector 的概念和 GCC 实现 - Concept and GCC implementation of std::vector 为什么删除move构造函数会导致编译错误? - Why does deleting the move constructor cause a compile error? 为什么GCC可以编译std :: exception(“ some error msg”)而没有错误? - Why GCC can compile std::exception(“some error msg”) without error? 为什么编译顺序有时会在使用std :: map :: insert()时导致分段错误? - Why does compile order sometimes cause a segmentation fault when using std::map::insert()? 为什么将 std::mutex 引入成员 class 会产生此编译错误? - Why does introducing std::mutex to member class generate this compile error? 为什么std :: visit采用可变数量的变体? - Why does std::visit take a variable number of variants? C++:std::visit 不能在 gcc 下编译 - c++ : std::visit not compilable under gcc
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM