如何概括作用于不同类型向量的函数?
How to generalize the functions, which acting on a vector of different types?
我是 C++ 的新手,我似乎无法正确表述我的问题。由于 vectorize 和 map 的含义似乎与我正在寻找的不同(因此很难通过谷歌搜索解决方案)。
我有很多作用于任意类型的单个对象的函数。我想要一种通用方法(即模板或包装函数)将它们转换为作用于任意数量的相同类型对象的向量的函数。
一个例子:
int func1(int a) {return a+1;}
long func2(long a) {return a*10;}
vector<int> func1(vector<int> a_vec)
{
vector<int> out_vec;
for (int i = 0; i < a_vec.size(); i++)
out_vec.push_back(func1(a_vec[i]));
return out_vec;
}
vector<long> func2(vector<long> a_vec)
{
vector<long> out_vec;
for (int i = 0; i < a_vec.size(); i++)
out_vec.push_back(func2(a_vec[i]));
return out_vec;
}
模板似乎是必需的,但我对它们还没有太多经验,也不知道如何在这种情况下应用它们。任何 references/suggestions/comments 欢迎。
(另外请添加相关标签 - 因为我不确定正确的术语,所以我不确定如何标记它)。
此代码确实看起来非常适合某些模板。
template <typename T, typename TFunc>
std::vector<T> transform(const std::vector<T> &v, TFunc &&func)
{
std::vector<T> result;
result.reserve(v.size());
for (auto &&element : v)
result.push_back(std::invoke(func, element));
return result;
}
您可能会注意到该函数看起来与 std::transform
非常相似,后者适用于迭代器而不是向量。它可以被称为:
auto result = transform(v, &func1);
是的,您将需要模板,因为您不知道将使用此矢量化函数的类型。
让我们试试看:
#include <vector>
#include <iostream>
int func1(int i){ return i + 1; }
template<typename valueT, typename callableT>
std::vector<valueT> vectorize(const std::vector<valueT>& input, callableT funcToCall)
{
std::vector<valueT> result;
for (auto& x : input) result.push_back(funcToCall(x));
return result;
}
int main()
{
std::vector<int> iVector{2,3,5,7,11,13,17};
std::vector<int> output = vectorize(iVector, &func1);
for (const auto& x : output) std::cout << x << std::endl;
return 0;
}
正如评论中提到的@paler123,你可以使用std::transform
来完成这项工作+一个小的模板化功能。
因为你的两个函数在函数签名上有相似之处
i.e, Type function(Type arg)
我选择了类型函数指针作为模板函数参数。
template<typename Type>
std::vector<Type> func(const std::vector<Type>& a_vec, Type(*func)(Type))
{
std::vector<Type> out_vec; out_vec.reserve(a_vec.size());
std::transform(a_vec.begin(), a_vec.end(), std::back_inserter(out_vec), func);
return out_vec;
}
现在在 main()
中,您可以显式指定类型或保留原样,让编译器进行类型推导。
auto result = func<int>({ 1,2,3,4 }, func1);
// also can
auto result2 = func({ 1, 2, 3, 4 }, func2);
我是 C++ 的新手,我似乎无法正确表述我的问题。由于 vectorize 和 map 的含义似乎与我正在寻找的不同(因此很难通过谷歌搜索解决方案)。
我有很多作用于任意类型的单个对象的函数。我想要一种通用方法(即模板或包装函数)将它们转换为作用于任意数量的相同类型对象的向量的函数。
一个例子:
int func1(int a) {return a+1;}
long func2(long a) {return a*10;}
vector<int> func1(vector<int> a_vec)
{
vector<int> out_vec;
for (int i = 0; i < a_vec.size(); i++)
out_vec.push_back(func1(a_vec[i]));
return out_vec;
}
vector<long> func2(vector<long> a_vec)
{
vector<long> out_vec;
for (int i = 0; i < a_vec.size(); i++)
out_vec.push_back(func2(a_vec[i]));
return out_vec;
}
模板似乎是必需的,但我对它们还没有太多经验,也不知道如何在这种情况下应用它们。任何 references/suggestions/comments 欢迎。
(另外请添加相关标签 - 因为我不确定正确的术语,所以我不确定如何标记它)。
此代码确实看起来非常适合某些模板。
template <typename T, typename TFunc>
std::vector<T> transform(const std::vector<T> &v, TFunc &&func)
{
std::vector<T> result;
result.reserve(v.size());
for (auto &&element : v)
result.push_back(std::invoke(func, element));
return result;
}
您可能会注意到该函数看起来与 std::transform
非常相似,后者适用于迭代器而不是向量。它可以被称为:
auto result = transform(v, &func1);
是的,您将需要模板,因为您不知道将使用此矢量化函数的类型。
让我们试试看:
#include <vector>
#include <iostream>
int func1(int i){ return i + 1; }
template<typename valueT, typename callableT>
std::vector<valueT> vectorize(const std::vector<valueT>& input, callableT funcToCall)
{
std::vector<valueT> result;
for (auto& x : input) result.push_back(funcToCall(x));
return result;
}
int main()
{
std::vector<int> iVector{2,3,5,7,11,13,17};
std::vector<int> output = vectorize(iVector, &func1);
for (const auto& x : output) std::cout << x << std::endl;
return 0;
}
正如评论中提到的@paler123,你可以使用std::transform
来完成这项工作+一个小的模板化功能。
因为你的两个函数在函数签名上有相似之处
i.e, Type function(Type arg)
我选择了类型函数指针作为模板函数参数。
template<typename Type>
std::vector<Type> func(const std::vector<Type>& a_vec, Type(*func)(Type))
{
std::vector<Type> out_vec; out_vec.reserve(a_vec.size());
std::transform(a_vec.begin(), a_vec.end(), std::back_inserter(out_vec), func);
return out_vec;
}
现在在 main()
中,您可以显式指定类型或保留原样,让编译器进行类型推导。
auto result = func<int>({ 1,2,3,4 }, func1);
// also can
auto result2 = func({ 1, 2, 3, 4 }, func2);