如何在不复制函数的情况下推导 const 和非常量类型?
How to deduce const and non-const type without duplicating functions?
假设我有这个函数:(它几乎对容器中的每个值运行一个函数,然后 returns 每次迭代结果的向量)
#include <vector>
using std::vector;
template<class F, class V>
auto vmap(const F &f, const V &v) -> vector<decltype(f(v[0]))> {
vector<decltype(f(v[0]))> result;
result.reserve(v.size());
for (auto &p : v)
result.push_back(f(p));
return result;
}
我不能这样称呼它:
vector<int> vint = {1,2,3,4,5};
vmap([](auto &p) {return p++;},vint);
因为参数 vector
是 const
,要实现它,我将不得不创建两个 vmap
得到非 const
V
和一个是 const
.
当有多个容器/vector
传递给一个函数时开始感觉太多了,因为它让我写2^containers_count
个函数。
是否有任何(-脏但有效的)解决方案?
如果您想让您的函数修改向量,请从您的函数参数中删除 const
。 v
的常量性将从提供给它的参数中推导出来。
你也不需要指定return类型,它会从return
语句中推导出来。
template<class F, class V>
auto vmap(const F &f, V &v) {
vector<decltype(f(v[0]))> result;
result.reserve(v.size());
for (auto&p : v)
result.push_back(f(p));
return result;
}
请注意 result.reserve(v.size());
仅适用于 std::vector
。如果您想推广您的算法,您需要删除该行,或专门针对它。
您可以使用采用常量向量的 lambda。
例如:
vmap([](const auto &p) {return p+1;}, vint);
或者修改vmap
,不需要常数向量。
例如:
auto vmap(const F &f, V &v)
您可以使用转发引用绑定到普通 l-value 引用(例如 std::vector<int>&
)和 r-value 引用(std::vector<int>&&
)。
缺点是您永远无法按值传递(仅 ref、const ref 或 r-value ref),但我认为这对您来说不是问题:
template<class F, class V>
auto vmap(F&& f, V&& v) {
vector<decltype(f(v[0]))> result;
result.reserve(v.size());
for (auto& p : v)
result.push_back(f(p));
return result;
}
请注意,如果您要传递一个 const 容器,则您传递的 lambda 必须适用于两个 const(谢谢,Miles),所以 p++
是不可能的(尽管要注意一个模板instantiation 修改输入而另一个不修改,这可能是意外的):
vector<int> vint = {1,2,3,4,5};
vmap([](auto &p) {return p++;},vint);
const std::vector<int> vint2 = vint;
vmap([](auto &p) {return p+1;},vint2);
假设我有这个函数:(它几乎对容器中的每个值运行一个函数,然后 returns 每次迭代结果的向量)
#include <vector>
using std::vector;
template<class F, class V>
auto vmap(const F &f, const V &v) -> vector<decltype(f(v[0]))> {
vector<decltype(f(v[0]))> result;
result.reserve(v.size());
for (auto &p : v)
result.push_back(f(p));
return result;
}
我不能这样称呼它:
vector<int> vint = {1,2,3,4,5};
vmap([](auto &p) {return p++;},vint);
因为参数 vector
是 const
,要实现它,我将不得不创建两个 vmap
得到非 const
V
和一个是 const
.
当有多个容器/vector
传递给一个函数时开始感觉太多了,因为它让我写2^containers_count
个函数。
是否有任何(-脏但有效的)解决方案?
如果您想让您的函数修改向量,请从您的函数参数中删除 const
。 v
的常量性将从提供给它的参数中推导出来。
你也不需要指定return类型,它会从return
语句中推导出来。
template<class F, class V>
auto vmap(const F &f, V &v) {
vector<decltype(f(v[0]))> result;
result.reserve(v.size());
for (auto&p : v)
result.push_back(f(p));
return result;
}
请注意 result.reserve(v.size());
仅适用于 std::vector
。如果您想推广您的算法,您需要删除该行,或专门针对它。
您可以使用采用常量向量的 lambda。 例如:
vmap([](const auto &p) {return p+1;}, vint);
或者修改vmap
,不需要常数向量。
例如:
auto vmap(const F &f, V &v)
您可以使用转发引用绑定到普通 l-value 引用(例如 std::vector<int>&
)和 r-value 引用(std::vector<int>&&
)。
缺点是您永远无法按值传递(仅 ref、const ref 或 r-value ref),但我认为这对您来说不是问题:
template<class F, class V>
auto vmap(F&& f, V&& v) {
vector<decltype(f(v[0]))> result;
result.reserve(v.size());
for (auto& p : v)
result.push_back(f(p));
return result;
}
请注意,如果您要传递一个 const 容器,则您传递的 lambda 必须适用于两个 const(谢谢,Miles),所以 p++
是不可能的(尽管要注意一个模板instantiation 修改输入而另一个不修改,这可能是意外的):
vector<int> vint = {1,2,3,4,5};
vmap([](auto &p) {return p++;},vint);
const std::vector<int> vint2 = vint;
vmap([](auto &p) {return p+1;},vint2);