如何在不复制函数的情况下推导 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);

因为参数 vectorconst,要实现它,我将不得不创建两个 vmap 得到非 const V 和一个是 const.

当有多个容器/vector传递给一个函数时开始感觉太多了,因为它让我写2^containers_count个函数。

是否有任何(-脏但有效的)解决方案?

如果您想让您的函数修改向量,请从您的函数参数中删除 constv 的常量性将从提供给它的参数中推导出来。

你也不需要指定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;
}

Demo

请注意,如果您要传递一个 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);