Reputation: 6999
I'm working with persistent data structures.
I'll have a complex class that I need to create a new instance but with one or more fields with different values.
struct Data {
int field1; int field2; int field3; // etc.
public:
Data withField2(int newField2) {
return { field1, newField2, field3 };
}
};
int main()
{
Data d = { 1, 2, 3 };
std::cout << d.field2 << std::endl;
Data newD = d.withField2(4);
std::cout << newD.field2 << std::endl;
}
Worst case, I can create a bunch of withField1(newField1Value)
methods as above but there will be enough fields such that it would get really messy.
Also, I might want new values for multiple fields, so then there could be many more.
So, is there some magic way of saying
Data newData = data.with(field1Name = newField1, field2Name = newField2)
or something similar?
Upvotes: 4
Views: 99
Reputation: 50550
You cannot do that, but you can do something interesting with pointers to data members:
#include<iostream>
#include<functional>
struct Data {
int field1; int field2; int field3; // etc.
template<int Data::*M>
Data withField(int value) {
Data cpy = *this;
cpy.*M = value;
return cpy;
}
};
int main()
{
Data d = { 1, 2, 3 };
std::cout << d.field2 << std::endl;
Data newD = d.withField<&Data::field2>(4);
std::cout << newD.field2 << std::endl;
}
This way you don't have to write all the withField
member methods at least.
With a bit of machinery and metaprogramming, maybe you could also define a method that changes a bunch of data fields all at once.
Of course, this works fine as long as your fields are all of type int
.
Otherwise, you need more than one method or something like this:
template<typename T, T Data::*M>
Data withField(T value) {
Data cpy = *this;
cpy.*M = value;
return cpy;
}
That has to be invoked as:
Data newD = d.withField<int, &Data::field2>(4);
Upvotes: 3
Reputation: 179887
The problem appears to be that you are reinventing std::tuple
. But you didn't reinvent std::get<N>
.
Your implementation uses names, and to the compiler they're utterly arbitrary. There's no guarantee the field names occur in numerical order without gasps.
Upvotes: 1