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
a
std::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);