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