gpt4 book ai didi

c++ - 为什么 std::visit 必须有单一的返回类型?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:03:35 25 4
gpt4 key购买 nike

在使用 std::variantstd::visit 时,出现了以下问题:

考虑以下代码:

using Variant = std::variant<int, float, double>;

auto lambda = [](auto&& variant) {
std::visit(
[](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
std::cout << "int\n";
} else if (std::is_same_v<T, float>) {
std::cout << "float\n";
} else {
std::cout << "double\n";
}
},
variant);
};

如以下示例所示,它工作正常:

lambda(Variant(4.5));    // double
lambda(Variant(4.f)); // float
lambda(Variant(4)); // int

那么下面为什么会失败:

using Variant = std::variant<int, float, double>;

auto lambda = [](auto&& variant) {
std::visit([](auto&& arg) { return arg; }, variant);
};

auto t = lambda(Variant(4.5));

由于静态断言

static_assert failed due to requirement '__all<is_same_v<int
(*)(__value_visitor<(lambda at main.cc:25:7)> &&,
__base<std::__1::__variant_detail::_Trait::_TriviallyAvailable, int, float,
double> &), float (*)(__value_visitor<(lambda at main.cc:25:7)> &&,
__base<std::__1::__variant_detail::_Trait::_TriviallyAvailable, int, float,
double> &)>, is_same_v<int (*)(__value_visitor<(lambda at main.cc:25:7)> &&,
__base<std::__1::__variant_detail::_Trait::_TriviallyAvailable, int, float,
double> &), double (*)(__value_visitor<(lambda at main.cc:25:7)> &&,
__base<std::__1::__variant_detail::_Trait::_TriviallyAvailable, int, float,
double> &)> >::value' "`std::visit` requires the visitor to have a single
return type."

std::visit 显然可以推断出 arg 的类型,如成功示例所示。那为什么要求有一个单一的返回类型呢?

编译器是 Apple LLVM 版本 10.0.1 (clang-1001.0.46.4)gcc 版本 8.3.0 失败并出现类似错误。

最佳答案

std::visit 的返回类型仅取决于访问者的类型和传递给它的变体。这就是 C++ 类型系统的工作原理。

如果你想要std::visit要返回一个值,该值需要在编译时就已具有类型,因为在 C++ 中所有变量和表达式都具有静态类型。

事实上你传递了一个 Variant(4.5) (所以“显然访问会返回一个 double ”)在该特定行中不允许编译器改变类型系统的规则 - std::visit return type 根本无法根据您传递的变量 value 进行更改,并且不可能仅根据 type 确定一种返回类型访问者和变体的类型。其他一切都会产生极其奇怪的后果。

This维基百科文章实际上基本上讨论了您遇到的确切情况/问题,只是带有 if而不是更复杂的 std::visit版本:

For example, consider a program containing the code:

if <complex test> then <do something> else <signal that there is a type error>

Even if the expression always evaluates to true at run-time, most type checkers will reject the program as ill-typed, because it is difficult (if not impossible) for a static analyzer to determine that the else branch will not be taken.


如果您希望返回的类型为“变体类型”,则必须坚持使用 std::variant .例如,您仍然可以:

auto rotateTypes = [](auto&& variant) {
return std::visit(
[](auto&& arg) -> std::variant<int, float, double> {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
return float(arg);
} else if (std::is_same_v<T, float>) {
return double(arg);
} else {
return int(arg);
}
},
variant);
};

std::visit 的推导返回类型然后是std::variant<int, float, double> - 只要你不决定一种类型,你就必须留在一个变体中(或在单独的模板实例中)。您不能“欺骗”C++ 放弃使用变体上的身份访问者的静态类型。

关于c++ - 为什么 std::visit 必须有单一的返回类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56038711/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com