提问人:f1msch 提问时间:1/27/2023 最后编辑:f1msch 更新时间:1/27/2023 访问量:179
如何通过函数返回 map<int, variant> 的值?
How could return map<int, variant>'s value by a function?
问:
我想要一个地图来保存不同类型的值,所以我有一个像这样的地图
std::map<int, std::variant<int, std::string>> m ={{1,1},{2,"asd"}};
现在我想设计一个函数来通过它的键来获取值,比如
auto get(int key) {
...
return value;
}
也就是说,我想要的样子
get(1) -> 1
get(2) -> "asd"
那么这可能吗?如果是这样,确切的解决方案是什么?
新增内容:
是的,就设计目的而言,我想保存从配置文件中读取的配置数据。
阅读后,我需要进行一些类型更改或数据转换。 例如在配置文件中,例如
a=1
b=asd
看完后,我想把它保存为
m[“a”]=int(3) ---->引用并需要在读取其实际数据后加 2 m[“b”]=std::string(“asdasd”) ---->引用并需要将其加倍a=1
1
b=asd
所以我认为如果有一个接口函数通过键获取确切的值会更容易
答:
两种可能性:
A) 您希望返回其中之一,或者取决于传递给函数的索引。int
std::string
不可能。函数具有一种返回类型。也不是魔术。如果无法编写实际类型,则编译器也无法编写。auto
B) 您要返回地图。mapped_type
您可以从函数返回。std::variant<int, std::string>
你不能比 .您需要在编译时指定要检索的类型。如果你想得到任何一个或.get
std::variant::get
std::variant::get
int
std::string
可能有更好的方法来解决您的实际问题,您认为是解决方案的方法。一条评论(由 Eljay 撰写)提到了 std::visit
。在那里,您可以看到如何处理变体的几个示例。auto get(int key)
您不能完全使用此语法设计函数。试想一下:
int key = 0;
if (rand() % 2) {
key = 1;
} else {
key = 2;
}
auto value = get(key);
这是个谜语:
请告诉我返回类型和 .只能有一个答案,你只能用一种类型来回答,无论我问你这个问题多少时间,它都不会改变。
get
value
如果你不能回答,那么编译器也不能。
然而,这并不意味着你不能设计类似的东西来满足你的需求。
您可以只返回变体。这可能不完全是你要找的,但值得注意的是,因为它不会改变函数的任何输入。get
您也可以只发送预期的类型:
get<int>(key)
实现如下所示:
template<typename T>
auto get(int key) -> T {
return std::get<int>(m[key]);
}
如果你不知道预期的类型,那么你可以只发送一个访客:
get(key, [](auto value) -> std::size_t {
if constexpr (std::same_as<int, decltype(value)>) {
// do stuff with value as an int since it's a int here
return value + 1;
} else {
// do stuff with value as a string since it's a string here
return value.size();
}
});
实现如下所示:
auto get(int key, auto visitor) -> decltype(auto) {
return std::visit(visitor, m[key]);
}
如果我了解这些要求,您可以从中返回一个代理对象,该对象保留对 的引用,并且根据您对代理对象的操作,它可以适应。例:get
variant
#include <iostream>
#include <variant>
#include <map>
#include <string>
struct Foo {
using variant = std::variant<int, std::string>;
// the proxy object
struct proxy {
// assignment:
template<class T>
variant& operator=(T&& value) {
*data = std::forward<T>(value);
return *data;
}
// for static_cast to the wanted type
explicit operator int& () { return std::get<int>(*data); }
explicit operator std::string& () { return std::get<std::string>(*data); }
variant* data;
};
proxy get(int key) {
// return the proxy object
return proxy{&m[key]};
}
std::map<int, std::variant<int, std::string>> m = {{1,1}, {2,"asd"}};
};
它可以这样使用:
int main() {
Foo f;
// you need to know what it stores:
std::cout << static_cast<int>(f.get(1)) << '\n';
std::cout << static_cast<std::string>(f.get(2)) << '\n';
// assigning is simple:
f.get(1) = "hello world"; // was int, now std::string
f.get(2) = 2; // was std::string, now int
std::cout << static_cast<std::string>(f.get(1)) << '\n';
std::cout << static_cast<int>(f.get(2)) << '\n';
}
评论
std::variant
get
get
评论
get(1)
get(2)
std::variant<int,std::string>>
std::variant<int, std::string>
std::visit
int
string