在我的可变参数模板中获取UB,将可变数量的向量逐元素求和 [英] Getting UB in my variadic template summing a variable number of vectors element-wise
问题描述
我正在尝试创建一个函数 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 << " ";
}
}
输出:
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 << " ";
}
}
这篇关于在我的可变参数模板中获取UB,将可变数量的向量逐元素求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!