I have a class template, that creates a class with two members:
template<typename coordinateType, typename ...DataTypes>
class Object{
public:
std::tuple<coordinateType, coordinateType, coordinateType> position;
std::tuple<std::vector<DataTypes>...> plantData;
};
The issue is, rather than calling
auto myObject = Object<float, int, int, int>();
for an instance of Object with 3 ints of data, I want to clean this up and use two separate templates, without the unrelated "float" as the first argument.
Is there a way to implement this class so that it would be the equivalent of:
auto myObject = Object<float>();
myObject.track<int, int, int>();
And if not, is it possible to separate those two template arguments in any way, or am I stuck with grouping them together?
CodePudding user response:
If I understand you correctly, you'd like track<Ts>
to append Ts
to the list of DataTypes
. This can be achieved like:
template<typename coordinateType, typename ...DataTypes>
class Object{
public:
template<typename... Ts>
Object<coordinateType, ...DataTypes, Ts>
track() { return {}; } // you might add proper ctor call, element copy via tuple::cat, etc.
std::tuple<coordinateType, coordinateType, coordinateType> position;
std::tuple<std::vector<DataTypes>...> plantData;
};
CodePudding user response:
if you change the caller side a little, you can make track
to return a new class.
template<typename T, typename...Us>
struct Object{
std::tuple<T, T, T> position;
std::tuple<std::vector<Us>...> plantData;
};
// you can also give it a different name, here I use a specialization instead
template<typename T>
struct Object<T>{
template<typename...Us>
Object<T,Us...> track();
};
void foo(){
auto myObjectCreator = Object<float>();
auto myObject = myObjectCreator.track<int, int, int>();
}