专业化不包含在主模板中声明的数据

Specialization doesn't contain data that's declared in the primary template

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'

真实案例

其实我遇到这样一个问题:我需要一个虚函数,但是它的return类型不唯一,可能是一个std::set,一个std::vectorstd::list 或其他一些类型。然后我在想模板技术可能会有所帮助。这就是为什么我定义 class template<typename T> class CustomConfig.

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

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

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

CustomConfig<std::set<uint32_t>>CustomConfig<T> 专业化 ,即当 替换 CustomConfig<T> Tstd::set<uint32_t>,它并不像您所想的那样 CustomConfig<T> 推导出 。因此,它不继承 CustomConfig<T>.

的任何成员

两者完全不同类。

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

所以它没有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;
};

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

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

如果您的 CustomConfig 提供了其他可以从 class 模板中完成的通用功能,那么您可能更喜欢这种方法。您的设计总体上有点不舒服,并且似乎对任何一种封装都有一种“放松”的态度。你可能想更深入地考虑一下。