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};
}
};
I don't know why I got the error:
class CustomConfig<std::set<unsigned int> >' has no member named 'data'
REAL CASE
In fact, I got such an issue: I need a virtual function, but it's return type is not unique, it may be a std::set
, a std::vector
, std::list
or some other types. Then I was thinking the template technique might help. That's why I defined the class template<typename T> class CustomConfig
.
I hope this was not a serious XY problem... Obviously I misunderstood how template class works.
CodePudding user response:
To provide an alternative to the other answers, which all say you must add your data member, there's another option which is to derive from a template instantiation instead:
class CustomConfigSetOfUInt : public CustomConfig<std::set<uint32_t>> {
public:
void load() override {
this->data = {4, 5, 6};
}
};
If your CustomConfig
provides other generalized functionality that would benefit from being done in the class template, then you might prefer this approach. Your design in general is a bit uncomfortable and does seem to have a "relaxed" attitude toward encapsulation either way. You may want to have a deeper think about it.
CodePudding user response:
The specialization is a brand-new class (relative to the primary template), you have to declare the data member for it too (also the inheritting). E.g.
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;
};
CodePudding user response:
CustomConfig<std::set<uint32_t>>
is a specialization of CustomConfig<T>
, ie it replaces CustomConfig<T>
when T
is std::set<uint32_t>
, it does not derive from CustomConfig<T>
like you are thinking. As such, it does not inherit any of the members of CustomConfig<T>
.
The two are completely separate classes.
CodePudding user response:
That specialisation does not inherit from the template class, it is instead used in place of the templated class for a specific data type.
So it gets no data
or load()
, you have to provide them yourself, such as with:
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;
};
In any case, it's often a good idea to steer clear of more "generic" underlying types, as that can be a great assistance in discovering and repairing issues. By that, I mean something like type definitions to make things clearer:
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;
};