专业化不包含在主模板中声明的数据
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::vector
,std::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>
T
是 std::set<uint32_t>
,它并不像您所想的那样 从 CustomConfig<T>
推导出 。因此,它不继承 CustomConfig<T>
.
的任何成员
两者完全不同类。
该专业化不是从模板 class 继承的,而是用于代替特定数据类型的模板化 class。
所以它没有data
或load()
,你必须自己提供它们,例如:
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 模板中完成的通用功能,那么您可能更喜欢这种方法。您的设计总体上有点不舒服,并且似乎对任何一种封装都有一种“放松”的态度。你可能想更深入地考虑一下。
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::vector
,std::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>
T
是 std::set<uint32_t>
,它并不像您所想的那样 从 CustomConfig<T>
推导出 。因此,它不继承 CustomConfig<T>
.
两者完全不同类。
该专业化不是从模板 class 继承的,而是用于代替特定数据类型的模板化 class。
所以它没有data
或load()
,你必须自己提供它们,例如:
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 模板中完成的通用功能,那么您可能更喜欢这种方法。您的设计总体上有点不舒服,并且似乎对任何一种封装都有一种“放松”的态度。你可能想更深入地考虑一下。