Reputation: 399
I am trying to create a templatized vector, where the template type is determined by runtime parameters. I am aware that template stuff is completed before runtime, basically I am trying to funnel runtime input into a select few previously selected compile-time types. Here's a high level example of what I'd like to be able to do.
for (int i = 0; i < 2; ++i)
{
std::vector<getRunTimeT(i)> v;
// Do stuff with v
}
So, the vector should be initialized with a type selected by the runtime input.
So far, I've come to the conclusion that specialized template meta-programming is needed, and I have functionality that does what I need with compile-time parameters:
template<int i>
struct getCompileTimeT
{
typedef int type; // Base case, not expected to occur.
};
template<>
struct getCompileTimeT<0>
{
typedef int type;
};
template<>
struct getCompileTimeT<1>
{
typedef float type;
};
So I can do this:
std::vector<getCompileTimeT(1)> type; // Creates a vector of floats
So, somehow I need to bridge the compile-time aspect with some function that selects the correct type from the predefined template types. Here is an (illegal) example of how I envision this bridging function to work:
// Illegal demonstrative desired functionality
_type_ getRunTimeT(int select)
{
if (select == 0) return getCompileTimeT<0>;
else if (select == 1) return getCompileTimeT<1>;
}
So basically I am looking for something that 'bridges' between the compile-time functionality and the run-time functionality I've spoken of. Is this possible?
Thanks for any help you can give!
EDIT: Additional info:
Thank you for the solutions thus far; they have been very useful in helping me to understand this more thoroughly. I would like to provide an API-type function where a user can manipulate or use a type, which is 'dynamic' from their perspective. For example:
UserClass::function()
{
for (int i = 0; i < 2; ++i)
{
// getType() is something that may be a template parameter
myFunc<getType(i)>();
}
}
template<class T>
void UserClass::myFunc()
{
std::vector<T> v;
// Now the user has a vector to play with in their member function.
}
Upvotes: 3
Views: 2833
Reputation: 7595
You can consider using boost::variant<> as a type preserving generic value store:
http://www.boost.org/doc/libs/1_55_0/doc/html/variant/tutorial.html
The idea goes as following:
typedef boost::variant<
getCompileTimeT<0>,
getCompileTimeT<1>
> variant_type;
variant_type getRunTimeT(int select)
{
if (select == 0) return variant_type(getCompileTimeT<0>());
else if (select == 1) return variant_type(getCompileTimeT<1>());
}
At this stage, you can rely on variant's visitor pattern (described in variant's tutorial) to do type safe value dispatch down the line.
Depending on your application and with a bit of template magic (especially on c++11) you can define the original variant type concisely over range of getCompileTimeT<>
template parameters (so no need to enumerate all explicitly).
Upvotes: 1
Reputation: 46598
try this
template <class T>
void do_stuff()
{
std::vector<T> v;
// Do stuff with v
}
void do_suff_dispatch(int i)
{
switch (i)
{
case 0:
do_stuff<int>();
break;
case 1:
do_stuff<float>();
break;
}
}
for (int i = 0; i < 2; ++i)
{
do_suff_dispatch(i);
}
Upvotes: 3