使用 std::variant 作为类成员并应用访问者
Use std::variant as class member and apply visitor
我正在尝试使用 std::variant 作为类成员变量,然后使用运算符重载,以便此类的两个Variants
可以使用运算符plus
生成新变量。问题是 std::get 不像我想象的那样工作,所以我无法检索正确的(硬编码)字符串类型,以便使用AddVisitor
结构。
我收到一个编译错误,上面写着:no matching function for call to ‘get<0>(std::basic_string&)’
还有没有办法operator+
函数在没有if-else
语句的情况下检测类型?
我已经在 SO 中检查了很多答案,包括回答有关类似 Boost 功能的问题的答案,但我无法让它工作。
#include <iostream>
#include <variant>
#include <string>
#include "stdafx.h"
using Variant = std::variant<int, std::string>;
template<typename T>
struct AddVisitor
{
T operator()(T v1, T v2)
{
return v1 + v2;
}
};
class Var
{
Variant v;
public:
template<typename T>
Var(T value) : v(value) {}
Var operator+(Var& val)
{
// PROBLEM: This is a hard coded example that I want to use, so that concatenation of two strings happens.
return std::visit(AddVisitor<std::string>(), std::get<std::string>(v), std::get<std::string>(val.get()));
// Is there a way to get the correct type without if-else statements here?
}
Variant get()
{
return v;
}
};
int main()
{
Var x("Hello "), y("World");
// The expected output is this:
Var res = x + y;
return 0;
}
我希望能够使用 plus 运算符并连接两个字符串或两个整数并创建一个新的Var
变量。
好的,所以有几件事要谈。
首先,具有多个变体参数的std::visit
的访问者应接受变体类型的所有组合。在您的情况下,它应该接受:
(string, string)
(string, int)
(int, int)
(int, string)
如果对您来说只有string, string
和int, int
有效,您仍然需要接受其他组合才能编译代码,但您可以扔进去。
接下来,不应模板化访问者。相反,对于上述所有组合,operator()
应该是模板化的或重载的。
所以这是AddVisitor
:
struct AddVisitor
{
auto operator()(const std::string& a, const std::string& b) const -> Variant
{
return a + b;
}
auto operator()(int a, int b) const -> Variant
{
return a + b;
}
// all other overloads invalid
template <class T, class U>
auto operator()(T, U) const -> Variant
{
throw std::invalid_argument{"invalid"};
}
};
从文档中不清楚重载可以返回什么,但是除非所有返回都Variant
,否则我无法对其进行编译。幸运的是,编译器错误非常有帮助。(我需要检查标准)。
接下来,当您调用std::visit
时,您需要传递您拥有的variant
。
所以最终的代码是这样的:
auto operator+(Var& val) -> Var
{
return std::visit(AddVisitor{}, get(), val.get());
}
而且您确实可以随心所欲地使用它:
Var res = x + y;
代码的另一个问题是get
制作不必要的副本。而且std::variant
的副本制作起来并不便宜。所以我建议:
auto get() const -> const Variant& { return v; }
auto get() -> Variant& { return v; }
- 错误: 无效使用非静态数据成员"应用程序::应用程序构造函数"
- [[MASE_UNUSE]]应用于静态数据成员
- 通常应用方法,使用带有构造函数委托的 SFINAE 通过类模板的构造函数初始化成员
- 使用 std::variant 作为类成员并应用访问者
- 静态类模板成员:将"sizeof"应用于不完整类型无效
- 如何将概念应用于成员变量
- 用于将任意成员函数应用于对象容器容器的函子
- 如何在未评估的上下文中将成员函数的结果类型应用于类成员
- 静态类成员在动态库中与主应用程序不同
- 如何将 decltype 应用于运算符 [] 声明中的成员函数
- 在不减慢主应用程序速度的情况下在后端运行成员函数的技巧是什么
- 我可以在成员函数中的此指针上应用删除吗?
- 对给定结构成员应用操作的泛型方法
- 调用指向windows过程中C函数的函数的成员指针会导致应用程序崩溃
- 具有矢量成员的单例应用程序
- 应用于不完整类型的变量的成员访问表达式
- 定义接收指向其他类成员函数的指针的成员函数模板,添加应用函数
- 在单个(成员)函数的范围之外应用 RAII
- C++11的"default"只能应用于特殊成员功能吗?
- 对每个数据成员应用相同的函数 - 对异构类型进行转换