decltype不能解析嵌套向量.如何将模板用于嵌套向量? [英] decltype does not resolve nested vectors. How can I use templates for nested vectors?

查看:70
本文介绍了decltype不能解析嵌套向量.如何将模板用于嵌套向量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使+运算符重载以处理嵌套向量.我以为函数会在嵌套向量解析为基本类型之前调用它自己,但是编译时却得到了大量错误.我定义的矢量操作适用于基本类型,但不可变数量的嵌套矢量.唯一适用于嵌套向量的操作是<<<.运算符.

I am trying to overload the + operator to deal with nested vectors. I thought the function would call itself until the nested vectors resolve to basic types, but instead I get a huge list of errors when I compile it. My vector operations that I have defined work for basic types, but not a variable amount of nested vectors. The only operation that does work for nested vectors is the << operator.

main.cpp

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

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>
auto operator+(const std::vector<T1>& l, const std::vector<T2>& r) 
-> std::vector<decltype((l[0] + r[0]))>{
    typedef decltype((l[0] + r[0])) type;
    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), std::plus<type>());
    else
        std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans), std::plus<type>());
    return ans;
};

int main(){

    std::vector<std::vector<int>> vecvec = {{1,2,3},{4,5,6},{7,8,9}};
    std::vector<int> vec = {1,2,3};

    //Both output statements compile
    std::cout << vec    << std::endl;
    std::cout << vecvec << std::endl;

    //Does not compile 
    vecvec = vecvec + vecvec;

    //Does compile
    vec = vec + vec;

    return 0;
} 

现在,我无法使用嵌套向量进行类型提升.我认为我需要std :: plus T1或std :: plus T2,具体取决于升级规则.

Now I am not able to do type promotion with nested vectors. I think I need std::plus T1 or std::plus T2 depending on promotion rules.

template <typename T1, typename T2>
struct Add : std::plus<T1> { };//<- Here

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

我尝试了一下,结果是2而不是2.5.

I tried this and got an output of 2 instead of 2.5.

int main(){
    p(int) e = {1};
    p(double) q = {1.5};
    std::cout << (e + q) << std::endl;
    return 0;
}

推荐答案

我的其他答案在这里解释了您采用这种方法的原因失败和一种可能的解决方案.我只是想到了一个我认为值得分享的简单得多的东西.

My other answer on here explains why your approach failed and one possible approach for a solution. I just thought of a much, much simpler one that I thought was worth sharing.

问题在于您不能使用尾随返回类型,因为函数名称本身还不在范围内,因此您不能以这种方式使用递归.但是,没有什么可以阻止您编写元函数来确定返回类型应该是什么.元功能非常简单:

The problem is that you can't use a trailing return type because the function name itself isn't in scope yet, so you can't use recursion in that way. However, there's nothing to stop you from writing a metafunction to determine what the return type should be. That metafunction is very simple:

template <typename T1, typename T2>
struct nested_common_type :std::common_type<T1, T2> { };

template <typename T1, typename T2>
struct nested_common_type<std::vector<T1>, std::vector<T2>> {
    using type = std::vector<typename nested_common_type<T1,T2>::type>;
};

template <typename T1, typename T2>
using vector_common_type_t = std::vector<typename nested_common_type<T1,T2>::type>;

一旦有了返回类型,我们就可以只写一个普通的operator+:

And once we have the return type, we can just write one normal operator+:

template <typename T1, typename T2,
          typename R = vector_common_type_t<T1,T2>>
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;
}

这篇关于decltype不能解析嵌套向量.如何将模板用于嵌套向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆