定义处理可变数量的嵌套向量的"vector_cast"模板函数

Defining a "vector_cast" template function that works with a variable amount of nested vectors

本文关键字:vector 函数 cast 嵌套 处理 定义 向量      更新时间:2023-10-16

例如,我希望能够做这样的事情。

    std::vector<std::vector<int>>     e = {{ 1 },{ 2 }};
    std::vector<std::vector<double>>  q = {{1.5},{2.5}};
    q = vector_cast<double>(e);

但也vector_cast能够处理任意数量的嵌套向量。

这是我对此的尝试。 如果您注释掉标记的行不起作用,则代码有效。 问题是我需要帮助实现vector_cast函数。

#include <iostream>
#include <vector>
#include <algorithm>
#include <type_traits>

//Prints nested vectors
template<typename T1>
std::ostream& operator<<(std::ostream& stream, std::vector<T1> r){
    if(r.size() == 0){
        return stream;
    }
    else{
        stream << "(";
        for(int i = 0; i < r.size(); i++){
            if(i < (r.size() - 1)){
                stream << r[i] << ", ";
            }
            else{
                stream << r[i] << ")";
            }
        }
    }
    return stream;
};
//Adds nested vectors
template <typename T1, typename T2>
struct vector_common_type : std::common_type<T1, T2> { };
template <typename T1, typename T2>
struct vector_common_type<std::vector<T1>, std::vector<T2>> {
    using type = std::vector<typename vector_common_type<T1,T2>::type>;
};
template <typename T1, typename T2,
          typename R = std::vector<typename vector_common_type<T1,T2>::type>>
R operator+(const std::vector<T1>& l, const std::vector<T2>& r)
{
    R ans;
    std::transform(l.begin(),
                   l.begin() + std::min(l.size(), r.size()),
                   r.begin(),
                   std::back_inserter(ans),
                   [](const T1& lhs, const T2& rhs){ return lhs + rhs; });
    return ans;
}
//supposed to cast nested vectors
template <typename T1, typename T2>
struct vector_casting : std::condition<true,T1, T2> { };
template <typename T1, typename T2>
struct vector_casting<std::vector<T1>, std::vector<T2>> {
    using type = std::vector<typename vector_casting<T1,T2>::type>;
};
template <typename T1, typename T2,
          typename R = std::vector<typename vector_casting<std::vector<T1>,T2>::type>>
R vector_cast(const std::vector<T2>& r){
    R l(r.begin(),r.end());
    return l;
};
int main(){
    std::vector<std::vector<int>> e = {{ 1 },{ 1 }};
    std::vector<std::vector<double>> q = {{1.5},{2.5}};
    //This works
    q = q + q;
    //This does not work
    q = e;//<- needs cast, but my vector_cast does not work
    std::cout << q << std::endl;
    return 0;
}

使用矢量类型检测,您可以执行以下操作:

#include <iostream>
#include <vector>
// is_vector
// =========
namespace Detail {
    template<typename T>
    struct is_vector_test {
        static constexpr bool value = false;
    };

    template<typename ... Types>
    struct is_vector_test<std::vector<Types...>> {
        static constexpr bool value = true;
    };
}
template<typename T>
struct is_vector : Detail::is_vector_test<typename std::decay<T>::type>
{};
// vector_cast
// ===========
namespace Detail
{
    template <typename R, typename U, bool = is_vector<U>::value>
    struct vector_cast_implementation;
    // Elementary
    template <typename R, typename T>
    struct vector_cast_implementation<R, T, false>
    {
        typedef T value_type;
        typedef R result_type;
        static result_type apply(const value_type& value){
            // Simple Conversion
            return value;
        }
    };
    // Vectors
    template <typename R, typename U>
    struct vector_cast_implementation<R, std::vector<U>, true>
    {
        private:
        typedef vector_cast_implementation<R, U> base_cast;
        public:
        typedef std::vector<typename base_cast::value_type> value_type;
        typedef std::vector<typename base_cast::result_type> result_type;
        static result_type apply(const value_type& value){
            result_type result;
            result.reserve(value.size());
            for(const auto& element : value)
                result.push_back(base_cast::apply(element));
            return result;
        }
    };
}
template <typename R, typename T>
typename Detail::vector_cast_implementation<R, std::vector<T>>::result_type
vector_cast(const std::vector<T>& sequence){
    return Detail::vector_cast_implementation<R, std::vector<T>>::apply(sequence);
}
// test
// ====
int main() {
    std::vector<std::vector<std::vector<double>>> v3 = {
        {{ 0.0 , 0.1, 0.2 },
         { 1.0 , 1.1, 1.2 },
         { 2.0 , 2.1, 2.2 }},
        {{ 10.0 , 10.1, 10.2 },
         { 11.0 , 11.1, 11.2 },
         { 12.0 , 12.1, 12.2 }},
    };
    auto r3 = vector_cast<int>(v3);
    for(const std::vector<std::vector<int>>& r2 : r3) {
        for(const std::vector<int>& r1 : r2) {
            for(int e : r1)
                std::cout << e << " ";
        }
        std::cout << "n";
    }
}

要确定二进制向量运算的通用类型 R,您可以执行以下操作:

// vector_common_type
// ==================
namespace Detail
{
    template <typename U,typename V, bool = is_vector<U>::value, bool = is_vector<V>::value>
    struct vector_common_type_implementation;
    // Elementary
    template <typename U, typename V>
    struct vector_common_type_implementation<U, V, false, false>
    {
        typedef typename std::common_type<U, V>::type type;
    };
    // Vectors
    template <typename U, typename V>
    struct vector_common_type_implementation<std::vector<U>, std::vector<V>, true, true>
    {
        typedef typename vector_common_type_implementation<U, V>::type type;
    };
}
template <typename U, typename V>
struct vector_common_type;
template <typename U, typename V>
struct vector_common_type<std::vector<U>, std::vector<V>>
: public Detail::vector_common_type_implementation<std::vector<U>, std::vector<V>>
{};