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

Time:01-23

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.

CodePudding user response:

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. I.e. 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;
}
  • Related