在我的可变参数模板中获取UB,将可变数量的向量逐元素求和 [英] Getting UB in my variadic template summing a variable number of vectors element-wise

查看:63
本文介绍了在我的可变参数模板中获取UB,将可变数量的向量逐元素求和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个函数 AddVector ,该函数明智地添加(可变)数量的vectors.我想我明白了,但是当我得到错误的输出时,我显然没有.我要添加三个双精度矢量,每个矢量的大小为5,包含1 + 2 + 1,因此我希望

I'm trying to make a function AddVector that adds a (variable) number of vectors element wise. I think I got it, but as I get the wrong output, I clearly don't. I'm adding three vectors of doubles, each sized 5, containing 1+2+1, thus I expect

4 4 4 4 4

我知道

1.36234e-316 2.0326e-316 4 4 4 

显然是错误的(也许是未初始化的mem?)

Which is clearly wrong (maybe uninitialized mem?)

我使用CppInsights来查看翻译后的代码,但这似乎还可以.我在这里做什么错了?

I used CppInsights to look at the translated code, but that also seemed OK. What am I doing wrong here?

我的代码:

#include <vector>
template<typename T>
using Vec = std::vector<T>;

template<typename T>
auto SumAndIncVcIt(T& t) {
    return *t++;
}

template<typename T, typename... Args>
auto SumAndIncVcIt(T& t, Args&... args) {
    return *t++ + SumAndIncVcIt(args...);
}

#include <tuple>
template<typename... Args>
auto VcBegins(Args... args){
    return std::make_tuple(cbegin(args)...);
}

template<typename T, size_t... Is>
auto SumAndIncVcIts_impl(T& t, std::index_sequence<Is...>) {
    return SumAndIncVcIt(std::get<Is>(t)...);
}

template<class Tuple>
auto SumAndIncVcIts(Tuple& t) {
    return SumAndIncVcIts_impl(t,
        std::make_index_sequence<std::tuple_size<Tuple>{}>{}
    );
}

template<typename T, typename... Args>
Vec<T> AddVector(Vec<T> const& vt, Vec<Args> const&...  vargs){
    auto vret = Vec<T>(size(vt));
    auto vcIts = VcBegins(vt, vargs...);
    auto retIt = begin(vret);
    while(retIt != end(vret)){
        *retIt++ = SumAndIncVcIts(vcIts);
    }
    return vret;
}

#include<iostream>

int main() {
    constexpr auto size = 5;
    Vec<double> a(size, 1.0), b(size, 2.0);
    auto c = AddVector(a, b, a);

    for(auto const& el : c){
        std::cout << el << " ";
    }
}

p.s.是的,我应该使用SFINEA或概念.

p.s. yes, I should use SFINEA or concepts.

推荐答案

不确定您的问题在哪里,您自己发现的:) ...但这就是我将其实现的方式C ++ 17和大小:

Not sure where lies your problem yet, You found it yourself :) ... But this is how I would implement it with C++17 and sizes:

#include <vector>
#include <algorithm>

template<typename T>
using Vec = std::vector<T>;

template<typename T, typename...Args>
Vec<T> AddVector_impl(Vec<Args> const & ... vecs){
    auto sizes = {vecs.size()...};
    auto new_size = *std::min_element(sizes.begin(),sizes.end());

    Vec<T> res(new_size);

    for(std::size_t i=0;i<new_size;++i){
        res[i]=(vecs[i]+...);
    }
    return res;
}

// Ensures at least one vector, also sets its return type.
template<typename T, typename... Args>
Vec<T> AddVector(Vec<T> const& vt, Vec<Args> const&...  vargs){
    return AddVector_impl<T>(vt,vargs...);
}

#include <iostream>
int main() {
    constexpr auto size = 5;
    Vec<double> a(size, 1.0), b(size, 2.0);
    auto c = AddVector(a, b, a);

    for(auto const& el : c){
        std::cout << el << " ";
    }
}

Live Godbolt演示

输出:

4 4 4 4 4 

仅迭代器解决方案

#include <vector>
#include <algorithm>

template<typename T>
using Vec = std::vector<T>;


template<typename T, typename...Args>
Vec<T> AddVector_impl(Vec<Args> const & ... vecs){
    auto its = std::tuple(vecs.cbegin()...);

    auto add_inc = [](auto&... iters){
        return ((*iters++) + ... );
    };
    auto end_check = [&](auto&...iters){
        return ((iters!=vecs.cend()) && ...);
    };
    Vec<T> res;
    auto it = std::back_insert_iterator(res);
    while(std::apply(end_check,its)){
        *it++=std::apply(add_inc,its);
    }
    return res;
}

template<typename T, typename... Args>
Vec<T> AddVector(Vec<T> const& vt, Vec<Args> const&...  vargs){
    return AddVector_impl<T>(vt,vargs...);
}

#include <iostream>
int main() {
    constexpr auto size = 5;
    Vec<double> a(size, 1.0), b(size, 2.0);
    auto c = AddVector(a, b, a);

    for(auto const& el : c){
        std::cout << el << " ";
    }
}

Live Godbolt演示.

这篇关于在我的可变参数模板中获取UB,将可变数量的向量逐元素求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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