c++ - 如何使用访问者从变体返回特定类型?

标签 c++ templates c++17 variadic-templates std-variant

我有下面的代码,为什么 visitor1visitor2给出错误? 这是否意味着访问者不能返回变体中的一种类型?

#include <iostream>
#include <variant>


struct Visitor1
{
    template <class T>
    T operator()(const T & t) const
    {
        return (t);
    }
};

struct Visitor2
{
    int operator()(const int  & t) const
    {
        return std::get<int>(t);
    }

    char operator()(const char & t) const
    {
        return std::get<char>(t);
    }
};

struct Visitor3
{
    void operator()(const int & t) const
    {
        std::cout<<t;
    }
    void operator()(const char & t) const
    {
        std::cout<<t;
    }
};

int main()
{
    std::variant<int, char> v{char(100)};

    std::visit(Visitor3{}, v);

    auto t = std::visit(Visitor2{}, v);  //fails
    //auto t = std::visit(Visitor1{}, v); //fails
    std::cout << t;
}

我知道我可以使用 std::get() ,但问题是我只能使用 autostd::get() ,如果我做类似下面的事情,x在 if/else 范围之外无法访问:

bool b;
Variant v;
if (b)
{
   auto x = std::get<int>(v);
}
else
{
   auto x = std::get<char>(v);
}
// I want to do something with x here out of if/else

最佳答案

可以存在一种具有 C++ 的许多功能的语言,它可以满足您的需求。

为了执行您想要的操作,当您调用 std::visit 时,必须编写该函数其余部分的 N 个不同实现。

在这 N 个不同的实现中的每一个(在您的例子中是 2 个),变量的类型都会不同。

C++ 不是这样工作的。

与访问调用“相乘”的代码的唯一部分是访问者。

int main()
{
  std::variant<int, char> v{char(100)};

  std::visit([&](auto && t){
    std::cout << t;
  }, v);
}

我将 函数体的其余部分 放在访问者中。该代码针对可存储在访问者中的每种类型实例化一次。

从访问中返回的任何内容都会返回到调用范围的“单个实例”主体。

基本上,[&](auto&& t) lambda 执行您似乎想要的操作。


现在,我们可以做一些小技巧来稍微改变一下语法。

我最喜欢的是:

v->*visit*[&](auto&& val) {
  std::cout << val;
  return [val](auto&& x) { x << val; };
}->*visit*[&](auto&& outputter) {
  outputer(std::cout);
};

->*visit* 使用相对荒谬的元编程来允许

  1. 引起访问的命名运算符,

  2. 将访问的返回值融合到变体中。

但没有正常人会写出这样的代码。

关于c++ - 如何使用访问者从变体返回特定类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53159681/

相关文章:

c++ - std::hash 值在 char* 值上而不是在内存地址上?

c++ - 这些类型有什么问题?

c++ - std::function 的目标可调用在执行期间可以合法地破坏 std::function 吗?

c++ - 如何使用 Visual Studio 2017 Linux 支持编译和构建 C++17 代码?

c++ - 使用以下 has_member 函数时 SFINAE 无法正常工作的原因是什么?

c++ - 覆盖另一种方法使用的父类(super class)回调函数[C++]

c++ - 如果调用未覆盖的虚方法,如何强制编译器错误?

c++ - 模板化优先级队列导致对象成为指针。由 小码哥发布于

django - 包含标记错误.....指定的模板库无效。尝试加载时引发 ImportError

c++ - 为什么模板实例化中不允许使用 lambda?