This is a follow-up question to this question.
There, thanks to the answer of Jarod42, I managed to lift the member function get_first()
of a class template two_val<T>
to all classes of the form trait_vector<two_val<T>>
. See the code block below in order to see what these classes are and how the member function lift was achieved.
template<class T>
class two_val{
private:
T first_val;
T second_val;
public:
using type = T;
two_val() :
first_val {},
second_val {}
{}
T get_first(){return first_val;}
};
template <typename T> struct is_two_val : std::false_type {};
template <typename T> struct is_two_val<two_val<T>> : std::true_type {};
template<class T>
class trait_vector{
private:
std::vector<T> vec;
public:
trait_vector() : vec {} {}
auto get_first() requires (is_two_val<T>::value)
{
trait_vector<typename T::type> result{};
result.reserve(vec.size());
for(const auto& p : vec){
result.vec.push_back(p.get_first());
}
return result;
}
};
This all works well and is very nice.
But now I want to define further member functions of two_val<T>
, like T get_second()
, T add_first_and_second()
, bool check_equality_of_first_and_second()
, etc. For all these I would like to have corresponding lifted member functions for classes of the form trait_vector<two_val<T>>
. However, what I would like to avoid is to copy and paste the definition of trait_vector<two_val<T>>::get_first()
over and over again.
So what I'm aiming at is some member template function lift_from_two_val
of class trait_vector
that takes a member function of two_val<T>
with return type U
and turns it into a member function of trait_vector<two_val<T>>
with return type trait_vector<U>
. Then the lifts of the individual member functions of two_val<T>
could be defined as one-liners by simply applying lift_from_two_val
to the respective functions.
But I'm still too unfamiliar with the syntax of C++ to be sure if this is possible, let alone to actually make it work.
In case all of this is actually possible as I envision it: What if I want to lift from a bunch of other (template) classes to trait_vector
? Would there again be a way around copy and pasting the code from lift_from_two_val
?
template<std::invocable<T const> F>
auto lift(F f)
{
using RT = std::invoke_result_t<F, T>;
trait_vector<RT> result{};
result.reserve(vec.size());
for(const auto& p : vec){
result.vec.push_back(std::invoke(f, p));
}
return result;
}
now you can do this
trait_vector<two_val<int>> bob;
trait_vector<int> alice = bob.lift(&two_val<int>::get_first);
trait_vector<int> eve = bob.lift(&two_val<int>::get_second);
etc.