递归添加多个向量元素的函数以某种方式获得双精度作为参数

问题描述 投票:0回答:1

对于作业问题,我们必须使用可变参数模板和表达式模板。为了看看,他们做了一个练习来展示他们所谓的“简单”和“单循环”总和之间的区别。对于这个问题,“单循环”是无关紧要的;我遇到的问题是简单的求和。简单求和的想法是递归地添加向量,其中使用每个元素上的 for 循环来添加两个向量。我们不应该使用折叠表达式。我们可以假设向量具有相同的长度。

我有以下代码:

#include <vector>

template<typename V, typename... T>
std::vector<V> add_vectors_simple(
    const std::vector<V>& head, const T&... tail)
{
    std::vector<V> result(head.size()); // DO NOT REMOVE OR CHANGE THIS LINE - IT IS NECESSARY FOR SPEC TESTS.
    
    std::vector<V> tail_sum = add_vectors_simple(tail...);
    
    for (size_t i = 0; i < result.size(); i++) {
        result[i] = head[i] + tail_sum[i];
    };
    
    return result;
}

template<typename V> // Specialization for single argument
std::vector<V> add_vectors_simple(
    const std::vector<V>& vec)
{
    return vec;
}

std::vector<double> test_add_vectors_simple(
    const std::vector<double>& a, const std::vector<double>& b,
    const std::vector<double>& c, const std::vector<double>& d)
{
    return add_vectors_simple(a, b, c, d);
}

#include <iostream>

int main()
{
    int n = 10000;

    std::vector<double> a(n);
    std::vector<double> b(n);
    std::vector<double> c(n);
    std::vector<double> d(n);

    return 0;
}

这会产生编译错误,但是,给出:

main.cpp:9:31: error: no matching function for call to 'add_vectors_simple'
    std::vector<V> tail_sum = add_vectors_simple(tail...);
                              ^~~~~~~~~~~~~~~~~~
main.cpp:9:31: note: in instantiation of function template specialization 'add_vectors_simple<double>' requested here
main.cpp:9:31: note: in instantiation of function template specialization 'add_vectors_simple<double, std::vector<double>>' requested here
main.cpp:9:31: note: in instantiation of function template specialization 'add_vectors_simple<double, std::vector<double>, std::vector<double>>' requested here
main.cpp:29:12: note: in instantiation of function template specialization 'add_vectors_simple<double, std::vector<double>, std::vector<double>, std::vector<double>>' requested here
    return add_vectors_simple(a, b, c, d);
           ^
main.cpp:4:16: note: candidate function template not viable: requires at least argument 'head', but no arguments were provided
std::vector<V> add_vectors_simple(
               ^
1 error generated.

我不明白为什么会出现这个错误。由于类型推导失败,尾部的解包是否会以某种方式剥离双精度而不是向量?

编辑:正如@Raymond Chen在评论中指出的那样,问题是基本情况出现在递归情况之后,因此当它应该使用基本情况时它将使用递归情况。调换顺序就可以解决问题

c++ recursion vector variadic-templates
1个回答
0
投票

问题已经在评论中指出,所以这不是问题的答案,但不能在评论中创建代码块……我建议的事情:

  1. 它不必是递归的。
  2. 它应该始终获得正确的返回类型:当
    head
    int
    s的向量并且
    double
    s位于
    tail
    中的任何位置时,它的总和应该是
    double
    s,而不是
    int
    s。
  3. 如果数字不平凡,例如GNU MP 数量很大,它至少应该尝试一些(完美的)转发,以防万一输入向量是一次性的。
  4. 不应该坚持输入是向量;任何具有正确数量元素的可索引容器都可以。 (这会打开一罐漂亮的 map<size_t, SomeNumber>
     蠕虫,而不是 
    vector
     内的完整 
    tail...
    ,默认为零等)
template <typename V, typename... T> auto add_vectors_simple(V &&head, T &&...tail) -> std::vector<decltype((head[0] + ... + tail[0]))> { std::vector<decltype((head[0] + ... + tail[0]))> result; result.reserve(head.size()); for (size_t i{}; i < head.size(); ++i) result.emplace_back( (std::forward<V>(head)[i] + ... + std::forward<T>(tail)[i])); return result; }
我们来测试一下。 (最后(第四)个案例最重要。)

const std::vector<int> is{1, 2, 3, 4}; const std::vector<double> ds{4.5, 3.5, 2.5, 1.5}; for (auto x : add_vectors_simple(is, is)) std::cout << x << ' '; std::cout << std::endl; for (auto x : add_vectors_simple(ds, ds)) std::cout << x << ' '; std::cout << std::endl; for (auto x : add_vectors_simple(ds, is)) std::cout << x << ' '; std::cout << std::endl; for (auto x : add_vectors_simple(is, ds)) std::cout << x << ' '; std::cout << std::endl;
可能的输出:

2 4 6 8 9 7 5 3 5.5 5.5 5.5 5.5 5.5 5.5 5.5 5.5

如果Godbolt不是没用的话,那就在Godbolt上。

© www.soinside.com 2019 - 2024. All rights reserved.