C++ 从std::variant中的可能类型到std::visit的返回值
我正试着去想C++ 从std::variant中的可能类型到std::visit的返回值,c++,c++17,std-variant,C++,C++17,Std Variant,我正试着去想std::variant和std::visit,我正试图想出一种方法来指定我希望变量保存的两种类型(它们将进入我的std::variant),然后通过std::visit检索存储的数据。考虑下面的例子: #包括 #包括 #包括 结构打印类型{ void运算符()(常量int和数据){ std::cout错误消息很糟糕,但这里的问题是,变量的所有替代项在访问者中必须具有相同的返回类型。您的AllTypesOperatorOverload不遵守此规则,返回一个double和一个int,它
std::variant
和std::visit
,我正试图想出一种方法来指定我希望变量保存的两种类型(它们将进入我的std::variant
),然后通过std::visit
检索存储的数据。考虑下面的例子:
#包括
#包括
#包括
结构打印类型{
void运算符()(常量int和数据){
std::cout错误消息很糟糕,但这里的问题是,变量的所有替代项在访问者中必须具有相同的返回类型。您的AllTypesOperatorOverload
不遵守此规则,返回一个double
和一个int
,它们不是相同的类型
它的最新版本明确地告诉您这一点(以下是我包装的word):
这是有道理的,因为当你看这一行时,条的类型是什么
auto bar = std::visit(AllTypesOperatorOverload(), foo);
如果允许返回不同类型,Bar 的类型将取决于哪个替代代码<代码> Foo在运行时保持。这不能在C++中工作。
请注意,对于使用lambdas而不是外部定义的结构的std::visit
,有更简单的方法来创建访问者。如果constexpr
,则可以使用:
std::visit([](auto value) {
if constexpr (std::is_same_v<int, decltype(value)>) {
std::cout << "visiting int\n";
} else {
static_assert(std::is_same_v<double, decltype(value)>);
std::cout << "visiting double\n";
}
std::cout << "bar: " << value << '\n';
}, foo);
我想知道这个问题是否是因为double和int可以来回转换。它是用std::variant
复制的吗?oevrloaded的完整声明只有两行长…template struct重载:Ts…{using Ts::operator();};template重载(Ts…)->重载;
自我说明:gcc错误的编译器错误消息,铿锵良好(我知道,但有时我忘了检查…)。打印很好(但这不是我真正的问题),我正在尝试获取当前存储在foo
中的值(可以具有std::variant
中指定的任何类型)。有可能实现吗?@tom“我正在尝试获取当前存储在foo
中的值(该值可以具有std::variant
中指定的任何类型)。”问题是这没有意义。如果你得到这个值,bar
的类型是什么?变量可以是int
或double
,因此bar
的类型必须是int
和double
的叠加。这是不允许的。最接近的是制作bar
astd::variant
,但这就让我们从这里开始。相反,你应该将处理条形码的代码提升到访问者中,在那里它可以知道foo
@Justin中存储的内容的类型:谢谢你的澄清,我会看看是否可以这样做
std::visit([](auto value) {
if constexpr (std::is_same_v<int, decltype(value)>) {
std::cout << "visiting int\n";
} else {
static_assert(std::is_same_v<double, decltype(value)>);
std::cout << "visiting double\n";
}
std::cout << "bar: " << value << '\n';
}, foo);
template <typename... Lambdas>
struct overloaded : Lambdas...
{
template <typename... Fns>
explicit constexpr overloaded(Fns&&... fns)
: Lambdas(std::forward<Fns>(fns))...
{}
using Lambdas::operator()...;
};
template <typename... Lambdas>
overloaded(Lambdas...) -> overloaded<Lambdas...>;
// Usage:
std::visit(overloaded{
[](int value) {
std::cout << "visiting int\n";
std::cout << "bar: " << value << '\n';
},
[](double value) {
std::cout << "visiting double\n";
std::cout << "bar: " << value << '\n';
}
}, foo);