在不知道哪个值处于活动状态的情况下获取 std::visit 中的活动值
Getting active value in std::visit without knowing which value is active
我想在 std::variant 中获取活动值,但不知道哪个是活动的。我以为我可以写一个模板访问者并使用 std::visit 但它不起作用。
#include <variant>
#include <string>
#include <iostream>
struct Visit_configuration {
template<typename Data_type>
Data_type operator()(Data_type& t) const
{
return t;
}
};
int main()
{
std::variant<int, std::string> v;
v = "hello";
std::cout << std::visit(Visit_configuration(), v); // expect "hello"
std::cin.get();
}
MSVC 不编译并抛出:
error C2338: visit() requires the result of all potential invocations
to have the same type and value category (N4741 23.7.7
[variant.visit]/2).
note: see reference to function template instantiation 'int
std::visit&,0>(_Callable
&&,std::variant &)' being compiled
那么如何解决这个问题?
编辑:我想将获得的值也用于其他值,因此将 cout 放入模板并不是我想要的。
Return 访问者函数类型应该相同。
改为创建打印机访问者:
struct PrinterVisitor {
template<typename T>
void operator()(const T& t) const
{
std::cout << t;
}
};
int main()
{
std::variant<int, std::string> v;
v = "hello";
std::visit(PrinterVisitor{}, v); // expect "hello"
}
在您的情况下,您甚至可以使用 lambda:
int main()
{
std::variant<int, std::string> v;
v = "hello";
std::visit([](const auto& t){std::cout << t;}, v); // expect "hello"
}
问自己这个问题:
如果您不知道 variant
的哪一部分是活动的,那么 std::visit
的 return 类型是什么?
这是编译器必须回答的问题。答案不能是 "it depends" - 你(就像编译器一样)必须在编译时决定 恰好是一种类型 。 visit
调用在 运行 时不可能 return 不同类型。
如果您想使用不同的类型 "at runtime",您必须在以您要使用的类型为模板的函数中。换句话说,必须是不同的函数(或函数模板实例化)来处理"write an int to cout
"和"write a string to cout
"情况。您不能在同一个(非模板化)函数中执行此操作。
因此,这里直接的解决方案是将 std::cout <<
放入您的模板化访问者函数中 - 这就是访问的重点:指定在每种情况下应该发生什么。
如果您想 "use the obtained value maybe also for [some] other [purpose]",那么 "other purpose" 也应该是 the/a 访问者的一部分。只有这样你才能让 "other purpose" 一次处理不同的情况(例如在模板函数中)。否则,您必须在编译时就已经决定要使用哪种类型——编译器不会将该选择保留到以后(运行 时间)。
我想在 std::variant 中获取活动值,但不知道哪个是活动的。我以为我可以写一个模板访问者并使用 std::visit 但它不起作用。
#include <variant>
#include <string>
#include <iostream>
struct Visit_configuration {
template<typename Data_type>
Data_type operator()(Data_type& t) const
{
return t;
}
};
int main()
{
std::variant<int, std::string> v;
v = "hello";
std::cout << std::visit(Visit_configuration(), v); // expect "hello"
std::cin.get();
}
MSVC 不编译并抛出:
error C2338: visit() requires the result of all potential invocations to have the same type and value category (N4741 23.7.7 [variant.visit]/2).
note: see reference to function template instantiation 'int std::visit&,0>(_Callable &&,std::variant &)' being compiled
那么如何解决这个问题?
编辑:我想将获得的值也用于其他值,因此将 cout 放入模板并不是我想要的。
Return 访问者函数类型应该相同。
改为创建打印机访问者:
struct PrinterVisitor {
template<typename T>
void operator()(const T& t) const
{
std::cout << t;
}
};
int main()
{
std::variant<int, std::string> v;
v = "hello";
std::visit(PrinterVisitor{}, v); // expect "hello"
}
在您的情况下,您甚至可以使用 lambda:
int main()
{
std::variant<int, std::string> v;
v = "hello";
std::visit([](const auto& t){std::cout << t;}, v); // expect "hello"
}
问自己这个问题:
如果您不知道 variant
的哪一部分是活动的,那么 std::visit
的 return 类型是什么?
这是编译器必须回答的问题。答案不能是 "it depends" - 你(就像编译器一样)必须在编译时决定 恰好是一种类型 。 visit
调用在 运行 时不可能 return 不同类型。
如果您想使用不同的类型 "at runtime",您必须在以您要使用的类型为模板的函数中。换句话说,必须是不同的函数(或函数模板实例化)来处理"write an int to cout
"和"write a string to cout
"情况。您不能在同一个(非模板化)函数中执行此操作。
因此,这里直接的解决方案是将 std::cout <<
放入您的模板化访问者函数中 - 这就是访问的重点:指定在每种情况下应该发生什么。
如果您想 "use the obtained value maybe also for [some] other [purpose]",那么 "other purpose" 也应该是 the/a 访问者的一部分。只有这样你才能让 "other purpose" 一次处理不同的情况(例如在模板函数中)。否则,您必须在编译时就已经决定要使用哪种类型——编译器不会将该选择保留到以后(运行 时间)。