doplumi
doplumi

Reputation: 3118

How do I dynamically set a type?

I have been trying to write code that reads and inits a graph from a text input file.

Now, a graph is a template class Graph<K, V>, where K is the type of the nodes' key and V is the type of the nodes' value.

Let's say I want to take a Graph in input from a text file of such form:

char;int    // the types
a;b;c       // the keys
a;b,32;c,5  // edges starting from a
b;c,2       // edges starting from b

How do I store the type in a variable so to init the graph?

I would like to do something like this:

getline(file, value, ';');
string keyTypeString = value;
getline(file, value);
string valueTypeString = value;

type keyType = ...
type valueType = ...

Graph<keyType, valueType> graph = ...

How do I do that in C++? Is it even possible?

Upvotes: 0

Views: 93

Answers (3)

Daniel
Daniel

Reputation: 8441

If you know at compile time all possible types then use Boost.Variant. There are plenty of examples in the docs, but essentially you will have something like:

using type = boost::variant<char, int>;

std::string input;
std::getline(file, input);

type value;

try {
    value = boost::lexical_cast<int>(input);
} catch(const boost::bad_lexical_cast&) {
    value = input.front(); // char
}

Upvotes: 5

Garf365
Garf365

Reputation: 3707

It's not possible directly. C++ is a statically typed language. You should use a specific container able to store values whatever it's type. Take a look at http://www.boost.org/doc/libs/1_60_0/doc/html/any.html.

example from boost site :

#include <list>
#include <boost/any.hpp>

using boost::any_cast;
typedef std::list<boost::any> many;

void append_int(many & values, int value)
{
    boost::any to_append = value;
    values.push_back(to_append);
}

void append_string(many & values, const std::string & value)
{
    values.push_back(value);
}

void append_char_ptr(many & values, const char * value)
{
    values.push_back(value);
}

void append_any(many & values, const boost::any & value)
{
    values.push_back(value);
}

void append_nothing(many & values)
{
    values.push_back(boost::any());
}

So in your case, you can have a Graph<keyType, boost::any> graph. You should store somewhere which type is stored in your graph. But you will use a switch case statement at a moment when you have to deal with concrete type

Upvotes: 1

nvoigt
nvoigt

Reputation: 77324

No

In C++ this is not possible. Templates are a compile time construct. In other languages the same problem set is solved by a different construct they call "generics" where it is possible at runtime, but with templates in C++, it's not.

Upvotes: 0

Related Questions