I have many classes that use std::tie to make a tuple out of all the class attribute and use it to implement the == operator. They look like this:
class S
{
int number;
std::string text;
// and many other attributes...
auto tied() const noexcept { return std::tie(/* list all attributes here */); }
bool operator==(const S &o) const noexcept
{
return tied() == o.tied();
}
};
The classes have similar methods but very different attributes, so I want to create a base class they all inherit from and I want to include this bit of comparison in the base class.
However, since I can't define a virtual method returning auto, I'm struggling to write an abstract generic tied() method that should make a tuple out of all a derived class's attributes no matter how many of them or of which types they are.
Is this feasible?
Note: All attributes are either of trivial type or std::strings.
If there is a bounded number of elements, you can use CRTP and https://stackoverflow.com/a/39779537/1774667 to find the number of elements.
Using structured binding you can then build a tuple out of them.
This can be written in the CRTP base.
template<class T>
struct implement_equals {
friend bool operator!=(implement_equals const& lhs, implement_equals const& rhs ) {
return !(lhs==rhs);
}
T const& self() const {
return *static_cast<T const*>(this);
}
friend bool operator==(implement_equals const& lhs, implement_equals const& rhs) {
constexpr std::size_t count = construct_airity<T>;
return make_tie_from<count>{}(lhs.self()) == make_tie_from<count>{}(rhs.self());
}
};
next write make_tuple_from.
template<std::size_t>
struct make_tie_from;
template<>
struct make_tie_from<1> {
template<class T>
auto operator()( T const& t ) const {
auto const&[e0] = t;
return std::tie(e0);
}
};
then write 20 of those.
There are libraries that do this already for you you can find with a bit of googling. None of them are perfect, and they all require that the thing you are making a tie of expose the data publicly.
If you want to hide that data, create a struct that contains the data publicly to get the tie, and expose some way for implement_equals to get access to that struct (friend, whatever).
In c++14 you cannot do even this crippled for of reflection.
You can write implement_equals, but you have to manually write the tie. It is better than a virtual function, however.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With