我只是在学习使用std::variant,我想声明一个类型列表,它由(原则上)任意多个我的用户定义类型组成。即,像
template<typename T>
struct MyType{
T x;
};
template<typename T, int N>
MyClass{
public:
MyType<T> y;
int z = N;
double w;
MyClass(double b){
w = b;
}
};
template<typename T>
using my_type_list = std::variant<
MyClass<T,1>, MyClass<T,289>, MyClass<T,13>, ...., MyClass<T,5001>
>;
template<typename T>
std::vector<my_type_list> my_big_list = {
MyClass<T,1> { 2.0 },
MyClass<T,1> { 3.0 },
MyClass<T,289> { 9.4 },
MyClass<T, 13> { 1.3 },
MyClass<T, 5001> {2.5},
MyClass<T, 5001> {3.2},
..... etc....
};
Run Code Online (Sandbox Code Playgroud)
但N原则上整数可以是任何东西。
有什么办法可以做到吗?
我已经从 boost::variant 迁移到 std::variant,并遇到了障碍。
我在 boost 'type()' 中使用了一个很好的函数,它可以让你获得当前持有的 typeid。见https://www.boost.org/doc/libs/1_48_0/doc/html/boost/variant.html#id1752388-bb
如何使用 std::variant 实现这一点?
我在“type_index”上有一个无序映射键,它包含一些值“std::function”。我的变体,取决于类型,将决定我从地图中抓取什么函数来做一些操作。(我拥有的代码太大而无法发布)。
除了为特定 std::variant 编写特定访问者之外,还有其他实现想法吗?也许在 std::variant 上使用“index()”函数,然后索引到变体的类型列表中?有点像这样:如何从元组中获取第 N 个类型?
我有可以简化为的代码
std::variant<float, int> v[2] = foo();
int a = std::get<decltype(a)>(v[0]);
float b = std::get<decltype(b)>(v[1]);
Run Code Online (Sandbox Code Playgroud)
显然,如果返回错误的变体,这可能会抛出foo()异常,但这不是我的问题。(真正的代码有一个catch)。我的问题是这decltype(a)违反了“不要重复自己”原则。
是否有一种更简洁的方法来初始化 a 和 b,并且如果类型与预期不匹配,仍然会抛出异常?特别是,当我static_cast<int>(std::get<float>(v))尝试初始化int.
详题:为什么std:variant的operator=(T&& t)的noexcept规范不依赖于内部类型的析构函数的noexcept规范?
我可以在cppreference上看到
template <class T> variant& operator=(T&& t) noexcept(/* see below */);
Run Code Online (Sandbox Code Playgroud)
是
noexcept(std::is_nothrow_assignable_v<T_j&, T> &&
std::is_nothrow_constructible_v<T_j, T>)
Run Code Online (Sandbox Code Playgroud)
所以这个编译:
struct FooThrow {
~FooThrow() noexcept(false) {throw;}
};
static_assert(std::is_nothrow_assignable_v<std::variant<FooThrow, int>, int>);
Run Code Online (Sandbox Code Playgroud)
但它调用FooThrow的析构函数是noexcept(false):
std::variant<FooThrow, int> x;
x = 3; // throws
Run Code Online (Sandbox Code Playgroud)
这似乎不对.我错过了什么吗?
有没有办法创建一个预定义的类型列表,并在c ++ 17中的std :: variant中使用这些类型?这是我正在尝试做的,它编译,但不能像我希望的那样工作:
template < class ... Types > struct type_list {};
using valid_types = type_list< int16_t, int32_t, int64_t, double, std::string >;
using value_t = std::variant< valid_types >;
Run Code Online (Sandbox Code Playgroud) 我有两个需要以下功能的功能:
功能1:需要变量的地址来设置值。(它知道正确的类型)
函数2:是一个需要类型值的重载函数。
我需要一种基于枚举(指定要使用的类型)返回不同类型的方法。
我尝试使用 std::get 因为您可以使用数字来指定类型。然而,它要求 SelectedType 是一个常量表达式,但事实并非如此。
std::variant<uint8_t,int8_t,uint16_t,int16_t,double,float> Var;
std::get<SelectedTypeEnum>(Var)
Run Code Online (Sandbox Code Playgroud)
要点是使用一个变量来避免代码重复。
考虑以下代码:
enum Type{
Type_uint8_t,
Type_int8_t,
Type_uint16_t,
Type_int16_t,
Type_std::string
} TypeList;
GetTypeToUse(Type&){ /* Get/Set the type to use */ }
void SetValueBasedOnEnum(Type TypeToUse,void* ptr) {/* Function 1: Sets the value of the type */}
// This is a Overloaded Function which supports all types in the enum.
//"T" represents the type.
void DoStuffWithDifferentTypes(T ValueOfType) { /*Function 2:*/ }
Run Code Online (Sandbox Code Playgroud) 我正在尝试解决问题std::variant,std::visit并且我正在尝试提出一种方法来指定我希望我的变量保存的几种类型(将进入我的std::variant),然后通过std::visit. 考虑以下示例:
#include <iostream>
#include <variant>
#include <string>
struct PrintType {
void operator()(const int &data) {
std::cout << "visiting int node" << std::endl;
}
void operator()(const double &data) {
std::cout << "visiting double node" << std::endl;
}
};
struct SingleOperatorOverload {
int operator()(const int &data) {
std::cout << "visiting int node" << std::endl;
return data;
}
};
struct AllTypesOperatorOverload {
int operator()(const int &data) {
std::cout << "visiting int node" << std::endl; …Run Code Online (Sandbox Code Playgroud) 在分配给变体时,我觉得我遗漏了一些关于 int 类型提升的明显信息。
在 gcc 9.3.0 版本(Ubuntu 9.3.0-11ubuntu0~18.04.1)上,使用 -std=c++17 编译,以下代码编译失败:
#include <variant>
#include <iostream>
int main()
{
std::variant<long int, bool> v; // works fine if "long" is omitted
long int sanity = 1; // verify that we can assign 1 to a long int; works fine
std::cout << sizeof(sanity) << "\n";
v = 1; // compiler error here: why doesn't this assign to the long int variant of v?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
error: no match for ‘operator=’ (operand types …Run Code Online (Sandbox Code Playgroud) 我正在关注这个博客,并试图将动态多态性代码替换为使用std::variantand std::visit。但我无法让std::variant+std::visit比 virtual struct impl 更好地工作。速度慢了大约1.3-1.5 倍!(GCC 10.3 -O3 C++17)
用例如下。假设我们正在比较两个表的第 i 行和第 j 行。表可以具有异构类型的列。假设我们可以访问列缓冲区。我正在做的是测试,
def IndexEqual(Table:A, Table:B, int:i, int:j):
for c in range(A.num_cols):
if not A.column(c)[i] == B.column(c)[j]:
return False
return True
Run Code Online (Sandbox Code Playgroud)
对于动态多态性,我有以下内容int和float
struct Comp{
virtual bool comp(size_t i, size_t j) const = 0;
};
struct CompI: public Comp {
CompI(const int *data_1, const int *data_2) : data1(data_1), data2(data_2) {}
const int *data1, *data2;
bool …Run Code Online (Sandbox Code Playgroud) 所以我有两个变体(我缩短了它们,它们有更多类型):
std::variant<int *, double *> PtrVariant;
std::variant<int, double> ValueVariant;
Run Code Online (Sandbox Code Playgroud)
我想在它们之间复制价值。
这不起作用:
ValueVariant = *PtrVariant;
Run Code Online (Sandbox Code Playgroud)
这有效:
if (std::holds_alternative<int>(ValueVariant))
ValueVariant = *std::get<int *>(PtrVariant);
else if (std::holds_alternative<double>(ValueVariant))
ValueVariant = *std::get<double *>(PtrVariant);
Run Code Online (Sandbox Code Playgroud)
有没有办法在它们之间复制值而不检查变体持有什么类型?