对于作业问题,我们必须使用可变参数模板和表达式模板。为了看看,他们做了一个练习来展示他们所谓的“简单”和“单循环”总和之间的区别。对于这个问题,“单循环”是无关紧要的;我遇到的问题是简单的求和。简单求和的想法是递归地添加向量,其中使用每个元素上的 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在评论中指出的那样,问题是基本情况出现在递归情况之后,因此当它应该使用基本情况时它将使用递归情况。调换顺序就可以解决问题
问题已经在评论中指出,所以这不是问题的答案,但不能在评论中创建代码块……我建议的事情:
head
是int
s的向量并且double
s位于tail
中的任何位置时,它的总和应该是double
s,而不是int
s。 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上。