I have an attribute vector that can hold different types:
class base_attribute_vector; // no template args
template<typename T>
class raw_attribute_vector : public base_attribute_vector;
raw_attribute_vector<int> foo;
raw_attribute_vector<std::string> foo;
Based on run-time input for the type, I would like to create the appropriate data structure. Pseudocode:
std::string type("int");
raw_attribute_vector<type> foo;
Obviously, this fails. An easy, but ugly and unmaintainable workaround is a run-time switch/chained if:
base_attribute_vector *foo;
if(type == "int") foo = new raw_attribute_vector<int>;
else if(type == "string") ...
I read about run-time polymorphism with functors, but found it quite complex for a task that is conceptually easy.
What is the best and cleanest way to make this work? I played around with boost::hana
, finding that while I can create a mapping from string to type, the lookup can only be done at compile time:
auto types =
hana::make_map(
hana::make_pair(BOOST_HANA_STRING("int"), hana::type_c<int>),
hana::make_pair(BOOST_HANA_STRING("string"), hana::type_c<std::string>)
);
All possible types are known at compile-time. Any suggestions are highly appreciated. In a perfect solution, I would create the name->type mapping in a single place. Afterwards, I would use it like this
std::vector<base_attribute_vector*> foo;
foo.push_back(magic::make_templated<raw_attribute_vector, "int">);
foo.push_back(magic::make_templated<raw_attribute_vector, "std::string">);
foo[0]->insert(123);
foo[1]->insert("bla");
foo[0]->print();
foo[1]->print();
It is not required for this magic to happen at compile time. My goal is to have as readable code as possible.
boost::variant
, especially at its accessors (hint: it uses the visitor pattern). In fact ... maybe you should just useboost::variant
. – OxbridgeLiteralType
string class, so you could construct someconstexpr
instances of it and use those. That seems overly complex for this, though, and/or not what you want. – Gimbalsraw_attribute_vector<boost::variant<...>>
. This is an issue because to my understanding, the variant is as big as the biggest potential value. This would break the performance of the attribute vector. – Gurgleraw_attribute_vector<T>
should contain a member of typeboost::variant<std::vector<T>,std::vector<U>,...>
, or alternatively,std::vector<boost::variant<T,U,V...>>
, depending on whether or not the attribute vectors are homogenous in some type. In the first case theboost::variant
is always holding some kind ofstd::vector
- the size for which is always the same fixed small amount no matter what type it is instantiated at, in the second case it is directly holding astd::vector
which, likewise, has a fixed small size. Because: The vector holds its elements in the heap. – Oxbridgeboost::variant
s which holdstd::unique_ptr
s to the attribute value. In other words, store all attributes on the heap. – Oxbridge