![](/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.