简体   繁体   中英

Template setter setting a value of an unknown type. can I have a non template getter for this value?

I am writing a library for Command line arguments in c++. When a user declares a value they expect to receive from the command line, I want to return this value in a type they specify. For instance a command line program for adding multiple integers. The user would want to receive the numbers as int and so they can do that through a template set function that takes the type of what they would like to store. The users retrieve them using a get function. There is not really a problem but i am wondering if there is a better way to do what i am trying to achieve.

Main.cpp

#include <iostream>
#include <unordered_map>
#include <any>

class Arguements {
private:
    std::unordered_map<std::string, std::any> Values;
public:
    template<typename ReturnType>
    ReturnType get(std::string SearchValue);
    
    template<typename ValueType>
    void add(std::string Key);
};

template<typename ReturnType>
ReturnType Arguements::get(std::string Search)
{
    return std::any_cast<ReturnType>(Values[Search]);
}

template<typename ValueType>
void Arguements::add(std::string Key) 
{
    Values[Key] = ValueType{};
}

int main() 
{
    Arguements Example;

    Example.add<int>("ints");

    std::cout << Example.get<int>("ints") << "\n";

    // i want to be able to:
    //std::cout << Example.get("ints") << "\n"; 
    // and have it know to return an int
    return 0;
}

The problem

This works fine for what I am trying to do but is not optimal. I am using std::any but have also tried std::variant which is an option but std::any is simpler for showing what i mean. I am wondering if there is a better way to implement this sort of thing. Because this is a library I want simple ways to interface with this code. When someone calls get() they have to specify the type they want it to be returned as, this is a problem for my program. Is there a way to have get return the type of the value in the map? Or is there a better way I can structure my program to eliminate this?

I have just researched c++ meta programming techniques and features in hopes that something would be useful in this case, but i found nothing. I looked into meta programming libraries like boosts hana, mpl and fusion but if they could be used to solve my case i could not work out how. I also tried to have a function that would return auto but that did not work because it could not return more than one type.

Basically what you want is impossible in C++, since compiler should know return type of function at compile-time and you want it to be dependent from run-time.

But it still possible somewhat, but with a catch. You should get values based not on plain names, but rather some type-dependent argument. Ie something like this:

#include <iostream>
#include <unordered_map>
#include <any>

template<typename T>
struct ArgName {
  std::string name;
};

class Arguements {
private:
    std::unordered_map<std::string, std::any> Values;
public:
    template<typename ReturnType>
    ReturnType get(ArgName<ReturnType> SearchValue);
    
    template<typename ValueType>
    void add(ArgName<ValueType> Key);
};

template<typename ReturnType>
ReturnType Arguements::get(ArgName<ReturnType> Search)
{
    return std::any_cast<ReturnType>(Values[Search.name]);
}

template<typename ValueType>
void Arguements::add(ArgName<ValueType> Key) 
{
    Values[Key.name] = ValueType{};
}

int main() 
{
    Arguements Example;
    ArgName<int> ints("ints");

    Example.add(ints);

    std::cout << Example.get(ints) << "\n";

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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