我std::variant所有类都来自同一个基地.我想将变体转换为基础.
return std::visit( []( const Base& b ) { return b; }, v );
Run Code Online (Sandbox Code Playgroud)
这编译但发出警告C4172:返回本地变量的地址或临时
有没有办法访问std::variant到位,而无需制作本地或临时副本?
或者,如果这是不可能的,我怎样才能将值转换为void*可以使用static_cast?
更新:我认为这个例子应该是显而易见的,但事实并非如此,这是完整的复制品:
#include <variant>
struct Base {};
struct A : Base {};
struct B : Base {};
const Base& cast( const std::variant<A, B>& v )
{
return std::visit( []( Base const& b ) { return b; }, v );
}
int main()
{
std::variant<A, B> v{ A{} };
const auto& b = cast( v ); …Run Code Online (Sandbox Code Playgroud) 在 C++17 中,是否有一种简单的方法来 std::visit 带有重载自由函数的变体,或者我必须使用带有重载调用运算符的对象?
换句话说,是否可以添加一些简单的东西来使以下//ERROR!行编译为与该//OK!行在功能上相同?
#include<variant>
#include<iostream>
#include<list>
#include <boost/hana/functional/overload.hpp>
using boost::hana::overload;
struct A {};
struct B {};
void foo(A) { std::cout << "Got an A!\n"; }
void foo(B) { std::cout << "Got a B!\n"; }
using AorB = std::variant<A,B>;
constexpr auto foo_obj = overload(
[](A){std::cout << "Got an A!\n";},
[](B){std::cout << "Got a B!\n";});
int main() {
std::list<AorB> list{A(), B(), A(), A(), B()};
for (auto& each : list) std::visit(foo, each); // ERROR!
for (auto& …Run Code Online (Sandbox Code Playgroud) 这是受到我给新手用户的回答的启发,我建议他们使用 anstd::variant而不是 union。
通过工会,您可能会遇到如下情况:
struct Box {
struct Item { float value; };
using Boxes = std::vector<Box>;
union Value {
Item item;
Boxes boxes;
};
Value contents;
std::string label;
};
Run Code Online (Sandbox Code Playgroud)
(不完全是最初的问题,我在这里接受了一些诗意的许可。)并且使用一个变体,该类可能如下所示:
struct Box {
struct Item { float value; };
using Boxes = std::vector<Box>;
std::variant<Item, Boxes> contents;
std::string label;
};
Run Code Online (Sandbox Code Playgroud)
问题是,使用第一个变体,我可以写
if (box.contents.boxes.size() > 2) { foo(); }
Run Code Online (Sandbox Code Playgroud)
如果我已经确定会有子框,这就会起作用。
对于std::variant,我必须写:
if (std::get<Boxes>(box.contents).size() > 2) { foo(); }
Run Code Online (Sandbox Code Playgroud)
我觉得第二个版本的可读性要差得多,有点混乱,而且很分散注意力。另外 - 我必须知道 的类型boxes。
在我的代码中,我可以做些什么来让我的用户无需进行此类std::get()调用,并使他们的生活更加愉快?
我有一个类型为或std::vector的std::variant元素。如果迭代元素的类型为 ,我想遍历这个向量和一个额外的项目。但是,似乎不允许在运行时查询索引。我怎样才能做到这一点?intstd::set<int>insertstd::set<int>
#include <variant>
#include <set>
#include <vector>
int main()
{
using Variants = std::variant<int, std::set<int>>;
std::vector<Variants> var_vec;
var_vec.push_back(999);
std::set<int> a = {0,1,2};
var_vec.push_back(a);
for (int i = 0; i < var_vec.size(); ++i)
{
// if the element var_vec[i] is of type std::set<int>
if (var_vec[i].index() == 1) var_vec[i].insert(888); // !ERROR! How to achieve this?
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
error: '__gnu_cxx::__alloc_traits<std::allocator<std::variant<int, std::set<int, std::less<int>, std::allocator<int> > > >, std::variant<int, std::set<int, std::less<int>, std::allocator<int> > …Run Code Online (Sandbox Code Playgroud) 我有一个包含variant.
我想为该结构编写一个成员函数,该函数应该根据当前持有的类型变体运行代码。
但是,我在编译时遇到问题。我不想使用更多的“模板恶作剧”,比如使用单独的结构来定义operator(T&),因为它会进一步污染语法。这是一个例子:
struct Data {
std::variant<int, double> var;
//Into this function,multiple lambdas should be passed for cases that the user wants to handle
template<typename ... Funcs>
void apply(Funcs&&... funcs) {
std::visit(std::forward<Funcs>(funcs)...,var);
}
};
int main() {
Data d;
d.var = 4;
//variant holds int and lambda provided that takes int&, execute it:
d.apply([](int& i){
std::cout << "I am Int Poggers" << std::endl;
});
d.var = 0.0;
//variant holds double but no lambda passed that takes …Run Code Online (Sandbox Code Playgroud) 我想增加/减少 astd::variant的类型替代,基本上像这样:
using var_t = std::variant</*...*/>;
var_t var;
var.emplace< (var.index()+1) % std::variant_size<var_t> >(); // "increment" case, wrapping for good measure
Run Code Online (Sandbox Code Playgroud)
这里的问题是,虽然emplace期望 clang 的错误消息称为“显式指定的参数”,index但似乎不是constexpr.
明显的替代方案是这样的:
switch(var.index()){
0:
var.emplace<1>();
break;
1:
var.emplace<2>();
break;
// ...
variant_size<var_t>-1:
var.emplace<0>();
}
Run Code Online (Sandbox Code Playgroud)
但这就是我个人所说的“极其丑陋”和“维护背后的巨大痛苦”(特别是因为我必须维护这些块的两个几乎副本,以进行递增和递减)。
有没有更好/“正确”的方法来做到这一点?
如果该信息在任何方面都很重要,我的目标C++20是.clanglibstdc++
我想编写两个模板函数,一个捕获特定情况,另一个捕获与第一个情况不匹配的所有其他情况。我尝试使用 std::enable_if 来捕获特定情况,但编译器仍然因不明确的匹配而失败。如何编写这些重载函数以便编译器解决歧义?(我使用的是g++)
我尝试编写以下代码(这是重现问题的简化示例):
struct resource1_t{
};
struct resource2_t{
};
template <typename R, typename V>
struct unit_t{
typedef R resource_t;
typedef V value_t;
unit_t(value_t const& value):v(){}
value_t v;
value_t calcValue(resource_t const& r)const{return v;}
};
// Specific case (U::resource_t == R)
template <typename U, typename R, typename=std::enable_if_t<std::is_same_v<typename U::resource_t,R>>>
typename U::value_t callCalcValue(U const& u, R const& r){
return u.calcValue(r);
}
// General case (U::resource_t != R)
template <typename U, typename R>
typename U::value_t callCalcValue(U const& u, R const& r){
// Fail immediately! …Run Code Online (Sandbox Code Playgroud) std::variant 是 union 的替代品。
但union可以通过网络安全地在另一个平台(不同的编译器或arch)接收。std::variant 可以这样做吗?
比如我有两台机器A和B。A是windows,MSVC 19.4。B 是 Linux、gcc(或其他编译器,例如 MSVC 17)。我在A(或B)下编译代码:
std::variant<int, double> v = 1; // holds int.
f.write(&v, sizeof(v));
Run Code Online (Sandbox Code Playgroud)
B 可以使用以下代码从同一文件中读取正确的值吗?
std::variant<int, double> v;
f.read(&v, sizeof(v));
Run Code Online (Sandbox Code Playgroud)
如果 std::variant 无法安全地通过网络传递。有图书馆提供吗?增强::变体?或者也许创建一个像 std::variant 一样的自定义实现?
似乎std::visit在 lambda 中使用访问者调用并不简单,访问者是由值捕获的函数对象。虽然通过引用捕获工作正常。为什么会这样,是否有可能做到这一点?
在这种情况下,我不明白来自 MSVC 2017 的编译错误消息:
std::visit': 找不到匹配的重载函数
未能专门化函数模板未知类型 std::visit(_Callable &&,_Variants &&...)
我认为模板参数推导的行为与仅在std::visit没有包装调用的 lambda 的情况下进行调用非常相似。
说明问题的代码:
#include <variant>
struct T {
void operator()(int i) {};
void operator()(float f) {};
};
int main()
{
std::variant<int, float> v = 1;
T t;
// Does not compile.
//auto l1 = [t](auto v) { std::visit(t, v); };
//l1(v);
// Compiles.
auto l2 = [&t](auto v) { std::visit(t, v); };
l2(v);
// Compiles.
std::visit(t, v);
}
Run Code Online (Sandbox Code Playgroud) 我将如何制作std::vector包含a中包含的所有类型的默认构造实例的 a std::variant?
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
std::vector<TaskVariant> variants;
// I'd like to do this in a loop
variants.push_back(TypeA());
variants.push_back(TypeB());
variants.push_back(TypeC());
Run Code Online (Sandbox Code Playgroud) 我确信有一种简单的方法可以做到这一点,但在 SO 中找不到任何东西。在en.cppreference.com 中也找不到太多信息。
有没有办法简化 ,std::variant</*class types*/>以便我们可以声明可以std::variant作为参数的函数和类。
考虑这个例子:
我有一个向量,它充当以下内容的容器std::variant;
std::vector<std::variant<Car, Space, Human>> EntityContainer;
Run Code Online (Sandbox Code Playgroud)
如果我想将此向量作为参数传递给函数,则必须添加以下参数声明。
void Function(std::vector <std::variant<Car, Space, Human>>& container);
Run Code Online (Sandbox Code Playgroud)
我也许可以在这个例子中使用宏,但这并不能真正解决问题。
有没有更好的解决方案,而不是std::variant在项目的任何地方一遍又一遍地列出相同的类类型?
#include <iostream>
#include <vector>
#include <variant>
class Human
{
public:
void Talk(){ std::cout << "whass up\n"; }
};
class Car
{
public:
void RunEngine() { std::cout << "Vroom\n"; }
};
class Space
{
public:
void Expand() { std::cout << "Expand slowly\n"; }
};
struct VisitPackage …Run Code Online (Sandbox Code Playgroud) 我有以下向量
std::vector<std::pair<std::string, std::function<std::string(const PlayerFRDb&)>>> stringExtractors = {
{" TEAM ", extractTeam},
{" NAME ", extractName},
{" TYPE ", extractProperty4},
};
std::vector<std::pair<std::string, std::function<int(const PlayerFRDb&)>>> intExtractors = {
{" WS ", extractProperty0},
{" LS ", extractProperty1},
{" W ", extractProperty2},
{" L ", extractProperty3},
};
std::vector<std::pair<std::string, std::function<char(const PlayerFRDb&)>>> charExtractors = {
{" WAY ", extractProperty5},
};
std::vector<std::pair<std::string, std::function<double(const PlayerFRDb&)>>> doubleExtractors = {
{" LINE ", extractProperty6},
};
Run Code Online (Sandbox Code Playgroud)
为了更容易地使用这些函数,我想将它们集中到一个向量中,但问题是它们返回不同的类型。
我尝试使用 std::variant,但无法初始化向量,因为编译器打印出:“没有构造函数的实例与参数列表参数类型匹配 ({...}, {...}, {. ..}、{...}、{...}、{...}、{...}、{...}) "
using FuncVariant = std::variant<
std::function<std::string(const PlayerFRDb&)>, …Run Code Online (Sandbox Code Playgroud)