c++ 将成员函数从一个类模板提升到第二个类模板

oxiaedzo  于 2023-05-02  发布在  其他
关注(0)|答案(1)|浏览(117)

这是this question的后续问题。
在那里,由于Jarod42的答案,我设法将类模板two_val<T>的成员函数get_first()提升到形式为trait_vector<two_val<T>>的所有类。请参阅下面的代码块,以了解这些类是什么以及如何实现成员函数lift。

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;
    }
};

这一切都工作得很好,非常好。
但是现在我想定义two_val<T>的其他成员函数,如T get_second()T add_first_and_second()bool check_equality_of_first_and_second()等。对于所有这些,我希望有相应的trait_vector<two_val<T>>形式的类的提升成员函数。但是,我想避免的是一遍又一遍地复制和粘贴trait_vector<two_val<T>>::get_first()的定义。
所以我的目标是类trait_vector的某个成员模板函数lift_from_two_val,它接受一个返回类型为Utwo_val<T>的成员函数,并将其转换为返回类型为trait_vector<U>trait_vector<two_val<T>>的成员函数。然后,two_val<T>的各个成员函数的提升可以通过简单地将lift_from_two_val应用于相应的函数来定义为一行程序。
但是我对C++的语法还是太不熟悉了,不能确定这是否可行,更不用说让它真正工作了。
如果所有这些都像我想象的那样实际上是可能的:如果我想从一堆其他(模板)类提升到trait_vector,该怎么办?是否还有办法从lift_from_two_val复制和粘贴代码?

ht4b089n

ht4b089n1#

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;
}

现在你可以这么做了

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);

等等
Live example

相关问题