【问题标题】:Specialization doesn't contain data that's declared in the primary template专业化不包含在主模板中声明的数据
【发布时间】:2022-01-16 15:28:08
【问题描述】:
class Base {
public:
    virtual void load() = 0;
};

template<typename T>
class CustomConfig : public Base {
public:
    const T& getData() { return data; }
    T data;
};

template<>
class CustomConfig<std::set<uint32_t>> {
public:
    virtual void load() {
        this->data = {4, 5, 6};
    }
};

我不知道为什么会出现错误:

class CustomConfig<std::set<unsigned int> >' has no member named 'data'

真实案例

其实我遇到了这样一个问题:我需要一个虚函数,但是它的返回类型不是唯一的,可能是std::setstd::vectorstd::list或者其他一些类型。然后我在想模板技术可能会有所帮助。这就是我定义类template&lt;typename T&gt; class CustomConfig的原因。

我希望这不是一个严重的 XY 问题...显然我误解了模板类的工作原理。

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    要提供其他答案的替代方案,这些答案都说您必须添加数据成员,还有另一个选项是从模板实例化派生:

    class CustomConfigSetOfUInt : public CustomConfig<std::set<uint32_t>> {
    public:
        void load() override {
            this->data = {4, 5, 6};
        }
    };
    

    如果您的CustomConfig 提供了其他可以从类模板中受益的通用功能,那么您可能更喜欢这种方法。总体而言,您的设计有点不舒服,并且似乎对封装有一种“放松”的态度。您可能想要更深入地思考它。

    【讨论】:

    • 帮助很大。谢谢。实际上,我遇到了这样一个问题:我需要一个虚函数,但它的返回类型不是唯一的,它可能是std::setstd::vectorstd::list。然后我在想模板技术可能会有所帮助。这就是我定义类template&lt;typename T&gt; class CustomConfig的原因。
    【解决方案2】:

    特化是一个全新的类(相对于主模板),您也必须为其声明数据成员(也是继承)。例如

    template<>
    class CustomConfig<std::set<uint32_t>> : public Base {
    public:
        virtual void load() {
            this->data = {4, 5, 6};
        }
        const std::set<uint32_t>& getData() { return data; }
        std::set<uint32_t> data;
    };
    

    【讨论】:

      【解决方案3】:

      CustomConfig&lt;std::set&lt;uint32_t&gt;&gt;CustomConfig&lt;T&gt;特化,即当Tstd::set&lt;uint32_t&gt; 时,它替换 CustomConfig&lt;T&gt;,它不会派生 来自CustomConfig&lt;T&gt; 就像你在想的那样。因此,它不会继承CustomConfig&lt;T&gt; 的任何成员。

      两者是完全不同的类。

      【讨论】:

        【解决方案4】:

        该特化不继承自模板类,而是用于代替特定数据类型的模板类。

        所以它没有dataload(),您必须自己提供它们,例如:

        template<>
        class CustomConfig<std::set<uint32_t>> : public Base {
        public:
            virtual void load() {
                this->data = {4, 5, 6};
            }
            const std::set<uint32_t> &getData() { return data; }
            std::set<uint32_t> data;
        };
        

        无论如何,避开更“通用”的底层类型通常是个好主意,因为这可以极大地帮助发现和修复问题。我的意思是像类型定义这样使事情更清晰:

        using ConfigIntSet = std::set<uint32_t>; // Use *specific* type.
        template<>
        class CustomConfig<ConfigIntSet> : public Base {
        public:
            virtual void load() {
                this->data = {4, 5, 6};
            }
            ConfigIntSet data;
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-07-04
          • 2016-11-09
          • 2021-01-24
          • 2020-07-18
          • 1970-01-01
          • 1970-01-01
          • 2015-08-01
          • 1970-01-01
          相关资源
          最近更新 更多