【问题标题】:C++ class template specialization with pointers带指针的 C++ 类模板特化
【发布时间】:2016-01-28 19:27:23
【问题描述】:

我有一个如下格式的树结构:

template <typename DataType>
class Tree {

    DataType *accessData() { return data; } 

    Tree *child1, *child2;
    DataType *data;
};

template <typename DataType>
class Root : public Tree<DataType> {
    // root provides storage of nodes; when it goes out of scope, the
    // entire tree becomes invalid
    MemoryPool<Tree> nodeStorage;
    MemoryPool<DataType> dataStorage; 
};

我在我的程序中使用了这个模板的各种实例。效果很好。

然而,一个实例化使用DataType,它只是一个枚举(因此它与指针大小相同!)并且因为速度至关重要(无论是在构建树时还是在访问树时),我'宁愿这个实例化直接使用枚举而不是指针。我希望代码看起来如何(不严格)的示例:

Tree<BigClass> *foo = ...;
foo->accessData()->doBigClassThings();
Tree<int> *bar = ...;
int x = 4 + bar->accessInt();

现在我当然可以只保留当前模板,但我不喜欢这种额外的指针访问,尤其是需要在根目录中分配整数。关于如何专门化模板以提供此功能或其他方法的任何想法?

我尝试过像这样专门化模板(以及无数其他方式)

template <> Tree<int> { ... }

但我只是不断收到编译错误。任何帮助将不胜感激!

【问题讨论】:

    标签: c++ class templates pointers


    【解决方案1】:

    我建议使用特征类来推断存储在Tree 中的对象类型。

    // The default traits.
    template <typename DataType> struct TreeDataType
    {
       using Type = DataType*;
    };
    
    template <typename DataType>
    class Tree {
    
       // Define the data type using the traits class.
       using Data = typename TreeDataType<DataType>::Type;
    
       Data accessData() { return data; } 
    
       Tree *child1, *child2;
       Data data;
    };
    

    然后将TreeDataType 特化为MyEnum

    template <> struct TreeDataType<MyEnum>
    {
       using Type = MyEnum;
    };
    

    【讨论】:

    • 这看起来真的很简洁。方法名称没有区别,但这只是一个很小的负面影响。非常感谢!
    • 我认为这是最好的解决方案。所需的专业知识微不足道,我真的很喜欢这里的清洁。谢谢!
    • @bombax,我很高兴能提供帮助。祝你好运。
    【解决方案2】:

    我建议定义多个具有相同接口的data 类,您可以将它们用作DataType 模板参数。从数据的访问方式中抽象出数据的存储方式。

    template<typename T>
    class value_data
    {
    private:
        T _value;
    
    public:
        T& access() { return _value; }
        const T& access() const { return _value; }
    };
    
    template<typename T>
    class unique_ptr_data
    {
    private:
        std::unique_ptr<T> _value;
    
    public:
        T& access() { assert(_value != nullptr); return *_value; }
        const T& access() const { assert(_value != nullptr); return *_value; }
    };
    
    enum class my_enum { /* ... */ };
    
    class my_enum_data
    {
    private:
        my_enum _value;
    
    public:
        my_enum& access() { return _value; }
        const my_enum& access() const { return _value; }
    };
    

    然后,在您的Tree 类中,您可以通过它们的通用接口使用它们:

    template <typename DataType>
    class Tree {
    
        auto& accessData() { return data.access(); } 
    
        Tree *child1, *child2;
        DataType data;
    };
    

    【讨论】:

    • auto 的用法非常有趣,我将阅读您的全部答案,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    相关资源
    最近更新 更多