根据C中的运行时字符串选择模板

前端之家收集整理的这篇文章主要介绍了根据C中的运行时字符串选择模板前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个属性向量,可以包含不同的类型:
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;

根据类型的运行时输入,我想创建适当的数据结构.伪代码

std::string type("int");
raw_attribute_vector<type> foo;

显然,这失败了.如果出现以下情况,一个简单但丑陋且难以维护的解决方法是运行时切换/链接

base_attribute_vector *foo;
if(type == "int") foo = new raw_attribute_vector<int>;
else if(type == "string") ...

我读到了有关仿函数的运行时多态性,但发现它对于概念上容易的任务来说非常复杂.

使这项工作最好,最干净的方法是什么?我玩了boost :: hana,发现虽然我可以创建从字符串到类型的映射,但查找只能在编译时完成:

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

所有可能的类型在编译时都是已知的.任何建议都非常感谢.在一个完美的解决方案中,我将在一个地方创建name->类型映射.之后,我会像这样使用它

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();

这种魔法不需要在编译时发生.我的目标是拥有尽可能可读的代码.

解决方法

enum class Type
{
    Int,String,// ...
    Unknown
};

Type TypeFromString(const std::string& s)
{
    if (s == "int") { return Type::Int; }
    if (s == "string") { return Type::String; }
    // ...
    return Type::Unknown;
}

template <template <typename> class>
struct base_of;

template <template <typename> class C>
using base_of_t = typename base_of<C>::type;

然后是通用工厂

template <template <typename> class C>
std::unique_ptr<base_of_t<C>> make_templated(const std::string& typeStr)
{
    Type type = TypeFromString(typeStr);
    static const std::map<Type,std::function<std::unique_ptr<base_of_t<C>>()>> factory{
        {Type::Int,[] { return std::make_unique<C<int>>(); } },{Type::String,[] { return std::make_unique<C<std::string>>(); } },// ...
        {Type::Unknown,[] { return nullptr; } }
    };
    return factory.at(type)();
}

每个基地都需要专业化:

template <>
struct base_of<raw_attribute_vector> {
    using type = base_attribute_vector;
};

然后

auto p = make_templated<raw_attribute_vector>(s);

Demo

猜你在找的C&C++相关文章