加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 03:42:06 所属栏目:百科 来源:网络整理
导读:我有一个属性向量,可以包含不同的类型: class base_attribute_vector; // no template argstemplatetypename Tclass raw_attribute_vector : public base_attribute_vector;raw_attribute_vectorint foo;raw_attribute_vectorstd::string foo; 根据类型的运
我有一个属性向量,可以包含不同的类型:
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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读