首页 > 解决方案 > 在 C++ 中,有没有办法根据输入类是否抽象来定义模板行为?

问题描述

背景:我继承了一个大型系统,该系统使用模板来存储有关类的元数据,这可能会影响这个问题中固有的一些假设。

我正在使用一个模板注册系统,该系统部分基于此处找到的答案:有没有办法从包含其类名的字符串中实例化对象?. 宏在我的系统中是不行的,就像使用 boost(或者实际上是任何第三方 API)一样。

问题:我是否可以根据输入类型是抽象还是具体来创建行为不同的模板?

我正在寻找这样的东西(此处使用的代码直接从链接问题中接受的答案复制而来):

struct BaseFactory {
    typedef std::map<std::string, Base*(*)()> map_type;

    static Base * createInstance(std::string const& s) {
        map_type::iterator it = getMap()->find(s);
        if(it == getMap()->end())
            return 0;
        return it->second();
    }
protected:
    static map_type * getMap() {
        // never delete'ed. (exist until program termination)
        // because we can't guarantee correct destruction order 
        if(!map) { map = new map_type; } 
        return map; 
    }

private:
    static map_type * map;
};

template<typename T>
struct DerivedRegister : BaseFactory { 
    DerivedRegister(std::string const& s) { 
        getMap()->insert(std::make_pair(s, &createT<T>));
    }
};

// in derivedb.hpp
class DerivedB {
    ...;
private:
    static DerivedRegister<DerivedB> reg;
};

// in derivedb.cpp:
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");

除了我希望 DerivedRegister 根据 T 是抽象还是具体的不同而表现不同。在 T 是抽象的情况下,我希望 DerivedRegister 不会在映射中注册类型。

正如我在背景中提到的,我已经继承了一个已经存在于类层次结构(抽象或具体)上的现有系统。修改这个现有系统以添加地图注册是微不足道的;但是,抽象类会引起问题,因为对它们调用 new 是无效的。

在 BaseFactory 和 DerivedRegister 之间添加额外的继承和模板层不会有问题;但是,DerivedRegister 已经存在于每个班级中,我无法更改。

我认识到我可以添加一个独立于现有模板类的唯一注册系统,并且只将它添加到具体类中。我特别询问是否有一种解决方案可以在不使用第三方库的情况下在 C++11 中避免这种情况(我知道很多限制......)。

标签: c++c++11templates

解决方案


使用std::is_abstract

如果 T 是一个抽象类(即声明或继承至少一个纯虚函数的非联合类),则提供等于 的成员常量值true。对于任何其他类型,值为false


推荐阅读