通用函数中两个容器的总和
Sum of two containers in generic function
我需要编写一个通用函数来查找属于两个容器的元素的总和,并将这些元素放入一个向量中,该向量的类型是总和的结果。
EXAMPLE:
container one: 5 2 8 3 6
container two: 6 1 5
container of sum: 11 3 13 3 6
#include <iostream>
#include <cmath>
#include <vector>
template < typename tip1, typename tip2, typename tip >
tip sum_of_containers(tip1 blok1, tip2 blok2) {
std::vector < tip > a;
int n1 = std::distance(blok1.begin(), blok1.end());
int n2 = std::distance(blok2.begin(), blok2.end());
int n;
n = n1;
if (n2 > n1) n = n2;
for (int i = 0; i < n; i++)
a[i].push_back(blok1[i] + blok2[i]);
return a;
}
int main() {
int n1, n2, x;
std::cin >> n1;
std::vector < double > a, b, c;
for (int i = 0; i < n1; i++) {
std::cin >> x;
a.push_back(x);
}
std::cin >> n2;
for (int i = 0; i < n2; i++) {
std::cin >> x;
b.push_back(x);
}
c = sum_of_containers(a, b);
for (double i: c)
std::cout << i << " ";
return 0;
}
第 31 行错误:
no matching function for call to 'sum_of_containers
couldn't deduce template parameter 'tip'
你能给我一些解决这个问题的方法或想法吗?
问题很不清楚
“通用”可能表示不同的容器,例如 std::vector
或 std::deque
。但是在您的函数函数中,您使用的是 std::vector
和索引运算符 []
以及函数 push_back
。拥有所有这些的仅有的 2 个容器是 std::vector
和 std::deque
。所以,这没有多大意义。
“通用”的下一级将是 std::vector
具有不同的数据类型。但是对于 3 个模板参数,这意味着最坏的情况是我们添加 2 种不同的数据类型并将它们分配给第三种,同样是不同的数据类型。
从逻辑上讲,这会造成很多其他麻烦,需要进行类型转换,结果可能会导致精度损失。
如果我们查看函数 main,就会看到 3 std::vectors
,所有具有相同数据类型 double
的实例都被实例化了。这是有道理的。这将限制“通用”函数具有一个通用模板化参数,用于 std::vector
将持有的类型。
这可能如下所示:
#include <iostream>
#include <vector>
#include <algorithm>
template <typename T>
std::vector<T> sumOfVectors(const std::vector<T>& t1, const std::vector<T>& t2) {
// Get a reference to the larger vector
const std::vector<T>& largerVector = (t1.size() > t2.size()) ? t1 : t2;
// Create the resulting vector that can hold all elements
std::vector<T> result(largerVector.size(), {});
size_t index{};
for (; index < std::min(t1.size(),t2.size()); ++index)
result[index] = t1[index] + t2[index];
for (; index < largerVector.size(); ++index)
result[index] = largerVector[index];
return result;
}
int main() {
int n1, n2, x;
std::cin >> n1;
std::vector < double > a, b, c;
for (int i = 0; i < n1; i++) {
std::cin >> x;
a.push_back(x);
}
std::cin >> n2;
for (int i = 0; i < n2; i++) {
std::cin >> x;
b.push_back(x);
}
c = sumOfVectors(a, b);
for (double i : c)
std::cout << i << " ";
return 0;
}
当然你会为此定义一个运算符+
,这给了我们一个更直观的结果:
#include <iostream>
#include <vector>
#include <algorithm>
template <typename T>
std::vector<T> operator +(const std::vector<T>& t1, const std::vector<T>& t2) {
// Get a reference to the larger vector
const std::vector<T>& largerVector = (t1.size() > t2.size()) ? t1 : t2;
// Create the resulting vector that can hold all elements
std::vector<T> result(largerVector.size(), {});
size_t index{};
for (; index < std::min(t1.size(),t2.size()); ++index)
result[index] = t1[index] + t2[index];
for (; index < largerVector.size(); ++index)
result[index] = largerVector[index];
return result;
}
int main() {
int n1, n2, x;
std::cin >> n1;
std::vector < double > a, b, c;
for (int i = 0; i < n1; i++) {
std::cin >> x;
a.push_back(x);
}
std::cin >> n2;
for (int i = 0; i < n2; i++) {
std::cin >> x;
b.push_back(x);
}
c = a + b;
for (double i : c)
std::cout << i << " ";
return 0;
}
编辑
根据评论中给出的确切任务描述,我们可以提出所需的解决方案。
有点重
我们甚至可以添加类型特征来检查容器是否可迭代,但这可能太多了(尽管在 C++20 中使用 if constexpr (std::ranges::range<Container>)
之类的东西很容易
无论如何,请查看包含 2 个测试用例的更新解决方案。
#include <iostream>
#include <type_traits>
#include <vector>
#include <deque>
#include <forward_list>
#include <array>
#include <list>
#include <string>
// Some aliases to avoid heavy typing
template <typename T, typename U>
using Value_t = typename std::common_type<typename T::value_type, typename U::value_type>::type;
template <typename T, typename U>
using Vector_t = typename std::vector<Value_t<T, U>>;
template <typename T, typename U>
auto sum_of_containers(const T& c1, const U& c2) -> Vector_t<T, U> {
// Get rid of template parameters using aliases
using MyType = Value_t<T,U>;
using MyVector = Vector_t<T, U>;
// Here we will store the result
MyVector result{};
typename T::const_iterator c1Iter = std::begin(c1);
typename U::const_iterator c2Iter = std::begin(c2);
// Add, as long as there are the same number of elements in the containers
while ((c1Iter != std::end(c1)) and (c2Iter != std::end(c2)))
result.push_back(static_cast<MyType>(*c1Iter++) + static_cast<MyType>(*c2Iter++));
// If there should still be elements in one of the containers, then add them to the resulting vector as is
while (c1Iter != std::end(c1))
result.push_back(static_cast<MyType>(*c1Iter++));
while (c2Iter != std::end(c2))
result.push_back(static_cast<MyType>(*c2Iter++));
return result;
}
int main() {
// Test Data 0
std::deque<float> fl1 { 0.1f, 0.2f, 0.3f };
std::deque<double> dbl1 { 0.1, 0.2, 0.3, 0.4, 0.5 };
auto result0 = sum_of_containers(fl1, dbl1);
for (const auto& x0 : result0)
std::cout << x0 << '\n';
std::cout << '\n';
// Test Data 1
std::deque<int> dq{ -1,2,-3 };
std::forward_list<float> fl{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f };
auto result1 = sum_of_containers(dq, fl);
for (const auto& x1 : result1)
std::cout << x1 << '\n';
std::cout << '\n';
// Test Data 2
std::array<unsigned long, 3> ar1{ 1ul,2ul,3ul };
std::list<double> dbl{ 0.1, 0.2, 0.3, 0.4, 0.5 };
auto result2 = sum_of_containers(ar1, dbl);
for (const auto& x2 : result2)
std::cout << x2 << '\n';
std::cout << '\n';
}
.
.
.
当然,但不是必需的,您也可以在此处实现 + 运算符。
#include <iostream>
#include <type_traits>
#include <vector>
#include <deque>
#include <forward_list>
#include <array>
#include <list>
#include <string>
// Some aliases to avoid heavy typing
template <typename T, typename U>
using Value_t = typename std::common_type<typename T::value_type, typename U::value_type>::type;
template <typename T, typename U>
using Vector_t = typename std::vector<Value_t<T, U>>;
template <typename T, typename U>
auto operator +(const T& c1, const U& c2) -> Vector_t<T, U> {
// Get rid of template parameters using aliases
using MyType = Value_t<T, U>;
using MyVector = Vector_t<T, U>;
// Here we will store the result
MyVector result{};
typename T::const_iterator c1Iter = std::begin(c1);
typename U::const_iterator c2Iter = std::begin(c2);
// Add, as long as there are the same number of elements in the containers
while ((c1Iter != std::end(c1)) and (c2Iter != std::end(c2)))
result.push_back(static_cast<MyType>(*c1Iter++) + static_cast<MyType>(*c2Iter++));
// If there should still be elements in one of the containers, then add them to the resulting vector as is
while (c1Iter != std::end(c1))
result.push_back(static_cast<MyType>(*c1Iter++));
while (c2Iter != std::end(c2))
result.push_back(static_cast<MyType>(*c2Iter++));
return result;
}
int main() {
// Test Data 0
std::deque<float> fl1{ 0.1f, 0.2f, 0.3f };
std::deque<double> dbl1{ 0.1, 0.2, 0.3, 0.4, 0.5 };
auto result0 = fl1 + dbl1;
for (const auto& x0 : result0)
std::cout << x0 << '\n';
std::cout << '\n';
// Test Data 1
std::vector<int> ve{ -1,2,-3 };
std::forward_list<float> fl{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f };
auto result1 = ve + fl;
for (const auto& x1 : result1)
std::cout << x1 << '\n';
std::cout << '\n';
// Test Data 2
std::array<unsigned long, 3> ar1{ 1ul,2ul,3ul };
std::list<double> dbl2{ 0.1, 0.2, 0.3, 0.4, 0.5 };
auto result2 = ar1 + dbl2;
for (const auto& x2 : result2)
std::cout << x2 << '\n';
std::cout << '\n';
}
我需要编写一个通用函数来查找属于两个容器的元素的总和,并将这些元素放入一个向量中,该向量的类型是总和的结果。
EXAMPLE:
container one: 5 2 8 3 6
container two: 6 1 5
container of sum: 11 3 13 3 6
#include <iostream>
#include <cmath>
#include <vector>
template < typename tip1, typename tip2, typename tip >
tip sum_of_containers(tip1 blok1, tip2 blok2) {
std::vector < tip > a;
int n1 = std::distance(blok1.begin(), blok1.end());
int n2 = std::distance(blok2.begin(), blok2.end());
int n;
n = n1;
if (n2 > n1) n = n2;
for (int i = 0; i < n; i++)
a[i].push_back(blok1[i] + blok2[i]);
return a;
}
int main() {
int n1, n2, x;
std::cin >> n1;
std::vector < double > a, b, c;
for (int i = 0; i < n1; i++) {
std::cin >> x;
a.push_back(x);
}
std::cin >> n2;
for (int i = 0; i < n2; i++) {
std::cin >> x;
b.push_back(x);
}
c = sum_of_containers(a, b);
for (double i: c)
std::cout << i << " ";
return 0;
}
第 31 行错误:
no matching function for call to 'sum_of_containers
couldn't deduce template parameter 'tip'
你能给我一些解决这个问题的方法或想法吗?
问题很不清楚
“通用”可能表示不同的容器,例如 std::vector
或 std::deque
。但是在您的函数函数中,您使用的是 std::vector
和索引运算符 []
以及函数 push_back
。拥有所有这些的仅有的 2 个容器是 std::vector
和 std::deque
。所以,这没有多大意义。
“通用”的下一级将是 std::vector
具有不同的数据类型。但是对于 3 个模板参数,这意味着最坏的情况是我们添加 2 种不同的数据类型并将它们分配给第三种,同样是不同的数据类型。
从逻辑上讲,这会造成很多其他麻烦,需要进行类型转换,结果可能会导致精度损失。
如果我们查看函数 main,就会看到 3 std::vectors
,所有具有相同数据类型 double
的实例都被实例化了。这是有道理的。这将限制“通用”函数具有一个通用模板化参数,用于 std::vector
将持有的类型。
这可能如下所示:
#include <iostream>
#include <vector>
#include <algorithm>
template <typename T>
std::vector<T> sumOfVectors(const std::vector<T>& t1, const std::vector<T>& t2) {
// Get a reference to the larger vector
const std::vector<T>& largerVector = (t1.size() > t2.size()) ? t1 : t2;
// Create the resulting vector that can hold all elements
std::vector<T> result(largerVector.size(), {});
size_t index{};
for (; index < std::min(t1.size(),t2.size()); ++index)
result[index] = t1[index] + t2[index];
for (; index < largerVector.size(); ++index)
result[index] = largerVector[index];
return result;
}
int main() {
int n1, n2, x;
std::cin >> n1;
std::vector < double > a, b, c;
for (int i = 0; i < n1; i++) {
std::cin >> x;
a.push_back(x);
}
std::cin >> n2;
for (int i = 0; i < n2; i++) {
std::cin >> x;
b.push_back(x);
}
c = sumOfVectors(a, b);
for (double i : c)
std::cout << i << " ";
return 0;
}
当然你会为此定义一个运算符+
,这给了我们一个更直观的结果:
#include <iostream>
#include <vector>
#include <algorithm>
template <typename T>
std::vector<T> operator +(const std::vector<T>& t1, const std::vector<T>& t2) {
// Get a reference to the larger vector
const std::vector<T>& largerVector = (t1.size() > t2.size()) ? t1 : t2;
// Create the resulting vector that can hold all elements
std::vector<T> result(largerVector.size(), {});
size_t index{};
for (; index < std::min(t1.size(),t2.size()); ++index)
result[index] = t1[index] + t2[index];
for (; index < largerVector.size(); ++index)
result[index] = largerVector[index];
return result;
}
int main() {
int n1, n2, x;
std::cin >> n1;
std::vector < double > a, b, c;
for (int i = 0; i < n1; i++) {
std::cin >> x;
a.push_back(x);
}
std::cin >> n2;
for (int i = 0; i < n2; i++) {
std::cin >> x;
b.push_back(x);
}
c = a + b;
for (double i : c)
std::cout << i << " ";
return 0;
}
编辑
根据评论中给出的确切任务描述,我们可以提出所需的解决方案。
有点重
我们甚至可以添加类型特征来检查容器是否可迭代,但这可能太多了(尽管在 C++20 中使用 if constexpr (std::ranges::range<Container>)
无论如何,请查看包含 2 个测试用例的更新解决方案。
#include <iostream>
#include <type_traits>
#include <vector>
#include <deque>
#include <forward_list>
#include <array>
#include <list>
#include <string>
// Some aliases to avoid heavy typing
template <typename T, typename U>
using Value_t = typename std::common_type<typename T::value_type, typename U::value_type>::type;
template <typename T, typename U>
using Vector_t = typename std::vector<Value_t<T, U>>;
template <typename T, typename U>
auto sum_of_containers(const T& c1, const U& c2) -> Vector_t<T, U> {
// Get rid of template parameters using aliases
using MyType = Value_t<T,U>;
using MyVector = Vector_t<T, U>;
// Here we will store the result
MyVector result{};
typename T::const_iterator c1Iter = std::begin(c1);
typename U::const_iterator c2Iter = std::begin(c2);
// Add, as long as there are the same number of elements in the containers
while ((c1Iter != std::end(c1)) and (c2Iter != std::end(c2)))
result.push_back(static_cast<MyType>(*c1Iter++) + static_cast<MyType>(*c2Iter++));
// If there should still be elements in one of the containers, then add them to the resulting vector as is
while (c1Iter != std::end(c1))
result.push_back(static_cast<MyType>(*c1Iter++));
while (c2Iter != std::end(c2))
result.push_back(static_cast<MyType>(*c2Iter++));
return result;
}
int main() {
// Test Data 0
std::deque<float> fl1 { 0.1f, 0.2f, 0.3f };
std::deque<double> dbl1 { 0.1, 0.2, 0.3, 0.4, 0.5 };
auto result0 = sum_of_containers(fl1, dbl1);
for (const auto& x0 : result0)
std::cout << x0 << '\n';
std::cout << '\n';
// Test Data 1
std::deque<int> dq{ -1,2,-3 };
std::forward_list<float> fl{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f };
auto result1 = sum_of_containers(dq, fl);
for (const auto& x1 : result1)
std::cout << x1 << '\n';
std::cout << '\n';
// Test Data 2
std::array<unsigned long, 3> ar1{ 1ul,2ul,3ul };
std::list<double> dbl{ 0.1, 0.2, 0.3, 0.4, 0.5 };
auto result2 = sum_of_containers(ar1, dbl);
for (const auto& x2 : result2)
std::cout << x2 << '\n';
std::cout << '\n';
}
.
.
.
当然,但不是必需的,您也可以在此处实现 + 运算符。
#include <iostream>
#include <type_traits>
#include <vector>
#include <deque>
#include <forward_list>
#include <array>
#include <list>
#include <string>
// Some aliases to avoid heavy typing
template <typename T, typename U>
using Value_t = typename std::common_type<typename T::value_type, typename U::value_type>::type;
template <typename T, typename U>
using Vector_t = typename std::vector<Value_t<T, U>>;
template <typename T, typename U>
auto operator +(const T& c1, const U& c2) -> Vector_t<T, U> {
// Get rid of template parameters using aliases
using MyType = Value_t<T, U>;
using MyVector = Vector_t<T, U>;
// Here we will store the result
MyVector result{};
typename T::const_iterator c1Iter = std::begin(c1);
typename U::const_iterator c2Iter = std::begin(c2);
// Add, as long as there are the same number of elements in the containers
while ((c1Iter != std::end(c1)) and (c2Iter != std::end(c2)))
result.push_back(static_cast<MyType>(*c1Iter++) + static_cast<MyType>(*c2Iter++));
// If there should still be elements in one of the containers, then add them to the resulting vector as is
while (c1Iter != std::end(c1))
result.push_back(static_cast<MyType>(*c1Iter++));
while (c2Iter != std::end(c2))
result.push_back(static_cast<MyType>(*c2Iter++));
return result;
}
int main() {
// Test Data 0
std::deque<float> fl1{ 0.1f, 0.2f, 0.3f };
std::deque<double> dbl1{ 0.1, 0.2, 0.3, 0.4, 0.5 };
auto result0 = fl1 + dbl1;
for (const auto& x0 : result0)
std::cout << x0 << '\n';
std::cout << '\n';
// Test Data 1
std::vector<int> ve{ -1,2,-3 };
std::forward_list<float> fl{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f };
auto result1 = ve + fl;
for (const auto& x1 : result1)
std::cout << x1 << '\n';
std::cout << '\n';
// Test Data 2
std::array<unsigned long, 3> ar1{ 1ul,2ul,3ul };
std::list<double> dbl2{ 0.1, 0.2, 0.3, 0.4, 0.5 };
auto result2 = ar1 + dbl2;
for (const auto& x2 : result2)
std::cout << x2 << '\n';
std::cout << '\n';
}