如何在不重复函数的情况下推导出常量和非常量类型

How to deduce const and non-const type without duplicating functions?

本文关键字:常量 下推 类型 非常 情况下 情况 函数      更新时间:2023-10-16

假设我有这个函数:(它几乎对容器中的每个值运行一个函数,然后返回每次迭代结果的向量)

#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,要实现它,我将不得不创建两个非const V vmap和一个const

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

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

您可以使用转发引用绑定到两个普通的 l 值引用(例如 std::vector<int>& ) 和 r 值引用 ( 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;
}

演示

请注意,如果您要传递常量容器(谢谢,Miles),您传递的 lambda 必须适用于两个 const,因此p++是不可能的(尽管请注意一个模板实例化会修改输入,而另一个模板实例化不会,这可能是意想不到的):

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);
如果要

允许函数修改向量,请从函数的参数中删除constv的恒定性将从给出的论证中推断出来。

您也不需要指定返回类型,它将从 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)