简体   繁体   English

怎么可能返回map<int, variant> function 的价值?</int,>

[英]How could return map<int, variant>'s value by a function?

I want to have a map to save different types of value, so I have a map like我想要一个 map 来保存不同类型的值,所以我有一个 map 之类的

std::map<int, std::variant<int, std::string>> m ={{1,1},{2,"asd"}};

And Now I want to design a function to get the value by its key like现在我想设计一个 function 来通过它的键来获取值

auto get(int key) {
    ...
    return value;
}

That's to say what I want is like那就是说我想要的是什么样的

get(1) -> 1
get(2) -> "asd"

So is it possible?那有可能吗? If so what's the exact solution?如果是这样,确切的解决方案是什么?


ADDED :添加

Yes, as for the purpose of the design, I want to save config datas reading from config files.是的,至于设计的目的,我想保存从配置文件中读取的配置数据。

And after reading I need to make some type changing or data transform.阅读后我需要进行一些类型更改或数据转换。 Such as in config files like例如在配置文件中

a=1
b=asd

And after reading it, I want to save it as m["a"]=int(3) ---->refers a=1 and needs to plus 2 after reading its actual data 1 m["b"]=std::string("asdasd") ---->refers b=asd and needs to double it并且读完后想存为m["a"]=int(3) ---->指的是a=1需要在读完它的实际数据1 m["b"]=std后加2 ::string("asdasd") ---->引用b=asd并且需要将其加倍

So I think it will be easier if there is an interface function to get the exact value by the key所以我觉得如果有一个接口 function 通过key获取准确的值会更容易

Two possibilities:两种可能性:

A) You want to return either int or std::string depending on the index passed to the function. A) 您想根据传递给 function 的索引返回intstd::string

Not possible.不可能。 A function has one return type. function 有一种返回类型。 Also auto is not magic. auto也不是魔术。 If you cannot write the actual type, then the compiler can't either.如果您不能编写实际类型,那么编译器也不能。

B) You want to return the mapped_type of the map. B) 你想返回mapped_type的 mapped_type。

You can return std::variant<int, std::string> from the function.您可以从 function 返回std::variant<int, std::string>


Your get can't do much "better" than std::variant::get .您的get不能比std::variant::get做得“更好”。 With std::variant::get you need to specify at compile time what type you want to retrieve.使用std::variant::get您需要在编译时指定要检索的类型。 And there is no way around that if you want to get either int or std::string .如果您想获得intstd::string ,就没有办法解决这个问题。


There might be better ways to solve your actual issue, the one for which you thought auto get(int key) was the solution.可能有更好的方法来解决您的实际问题,您认为auto get(int key)是解决方案的方法。 A comment (by Eljay) mentions std::visit .一条评论(来自 Eljay)提到了std::visit There you can see a couple of examples of how to deal with variants.在那里你可以看到几个如何处理变体的例子。

You cannot exactly design a function with this syntax.您不能使用此语法准确设计 function。 Just imagine this:试想一下:

int key = 0;
if (rand() % 2) {
    key = 1;
} else {
    key = 2;
}

auto value = get(key);

Here's the riddle:这是谜语:

Please tell me the return type of get and the type of value .请告诉我get的返回类型和value的类型。 There can be only one answer and you can only answer with a single type that will remain unchanging no matter how much time I ask you this question.只能有一个答案,你只能用一种类型来回答,无论我问你这个问题多少次,它都不会改变。

If you can't answer, well, the compiler cannot either.如果你不能回答,那么编译器也不能。

However, it doesn't mean you can't design something similar that will do what you need.但是,这并不意味着您不能设计类似的东西来满足您的需要。

You could just return the variant.您可以只返回变体。 This might not be exactly what you're looking for, but it's worth noting since it doesn't change any of the input of the get function.这可能不是您要查找的内容,但值得注意,因为它不会更改get function 的任何输入。

You can also just send the expected type:您也可以只发送预期的类型:

get<int>(key)

The implementation would look like this:实现看起来像这样:

template<typename T>
auto get(int key) -> T {
    return std::get<int>(m[key]);
}

If you cannot know the expected type, then you could just send a visitor:如果您不知道预期的类型,那么您可以发送一个访问者:

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(); 
    }
});

The implementation would look like this:实现看起来像这样:

auto get(int key, auto visitor) -> decltype(auto) {
    return std::visit(visitor, m[key]);
}

If I understand the requirements, you could return a proxy object from get that keeps a reference to the variant and depending on what you do with the proxy object, it can adapt.如果我理解这些要求,您可以从get返回一个代理 object,它保留对variant的引用,并且根据您对代理 object 所做的操作,它可以适应。 Example:例子:

#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"}};
};

And it could be used like this:它可以这样使用:

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';
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM