c++ - 嵌套 vector 不遵循提升规则。解决方案有一个错误。

标签 c++ vector nested type-promotion

该程序添加了嵌套 vector ,但没有正确提升类型。我认为 std::plus 需要根据基本类型提升规则接受 T1 或 T2。最初的问题在这篇文章中(decltype does not resolve nested vectors. How can I use templates for nested vectors?)。

主要.cpp

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

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

template <typename T1, typename T2>
struct Add : std::plus<T1> { };//<-Here T1 or T2 depending on their types.

template <typename T1, typename T2>
struct Add<std::vector<T1>, std::vector<T2>>
{   
    auto operator()(const std::vector<T1>& l, const std::vector<T2>& r)
        -> std::vector<decltype(Add<T1,T2>{}(l[0], r[0]))>
    {
        using type = decltype(Add<T1,T2>{}(l[0], r[0]));
        std::vector<type> ans;

        if(l.size() == std::max(l.size(),r.size()))
            std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans), Add<T1,T2>{});
        else
            std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans), Add<T1,T2>{});
        return ans;
    };
};

template <typename T1, typename T2>
auto operator+(const std::vector<T1>& lhs, const std::vector<T2>& rhs)
    -> decltype(Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs))
{
    return Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs);
}

int main(){
    std::vector<int> e = {1};
    std::vector<double> q = {1.5};

    //Incorrect result = 2
    std::cout << (e + q) << std::endl;
    //Correct result = 2.5
    std::cout << (q + e) << std::endl;

    return 0;
}

最佳答案

您的代码中有两个问题(我对您的原始问题的回答有误)。第一个,如vsoftco所述正在使用 std::common_type 对于基本情况。

第二个是一个简单的错误。考虑这个 if 语句:

    if(l.size() == std::max(l.size(),r.size()))
        std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans), 
                       Add<T1,T2>{});
    else
        std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans), 
                       Add<T1,T2>{});

Add<T1,T2>::operator() ,在偏特化情况下,有两个参数:std::vector<T1>和一个 std::vector<T2> , 按此顺序。但是在if的两个分支声明,我们实际上是以不同的顺序调用它们。在true分支,我们以相反的顺序调用它们,所以只需要反转模板中的顺序:

    if(l.size() == std::max(l.size(),r.size()))
        std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans), 
                       Add<T2,T1>{});

实际上应该只删除 if -完全声明,因此特化案例现在是:

template <typename T1, typename T2> 
struct Add<std::vector<T1>, std::vector<T2>>
{   
    using R = decltype(Add<T1,T2>{}(std::declval<T1>(), std::declval<T2>()));

    std::vector<R> operator()(const std::vector<T1>& l, const std::vector<T2>& r)
    {
        std::vector<R> ans;

        std::transform(l.begin(),
                       l.begin() + std::min(l.size(), r.size()),
                       r.begin(),
                       std::back_inserter(ans),
                       Add<T1,T2>{});
        return ans;
    };
};

关于c++ - 嵌套 vector 不遵循提升规则。解决方案有一个错误。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30879255/

相关文章:

c++ - 如何解决 <<ClassName>> 的 "undefined reference to ` vtable 错误?

vector - 求向量的第二小值

python - 根据条件从嵌套列表中删除某些子列表

javascript - 使用 mongoose 进行嵌套数组查询

c++ - 使用继承的 luabind 和 std::shared_ptr

c++ - 计算表示稀疏 vector 的 map 之间的距离 C++

c++ - 将 std::vector 转换为数组

nested - 为什么在 tcl 中我们需要嵌套过程

c++ - 在 Windows 10 上使用 minGW 运行 SFML C++ 程序

c++ - C++ 中子类从基类继承了什么?