如何在不重复功能的情况下推导const和非const类型?

时间:2017-01-16 18:50:03

标签: c++ templates const template-deduction

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

#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个函数。

有没有(-dirty但正常工作)的解决方案呢?

3 个答案:

答案 0 :(得分:4)

您可以使用转发引用绑定到正常的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;
}

Demo

请注意,如果要传递const容器(感谢,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);

答案 1 :(得分:1)

如果要允许函数修改向量,请从函数参数中删除vreturn的常量将从赋予它的论证中推导出来。

您也不需要指定返回类型,它将从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仅适用于$command=(new Query()) ->select('*') ->from('ct_ostatniNaklady') ->where('pid=:pid',[':pid' => 1]) ->createCommand()->sql; var_dump($command);die; 。如果你想要推广你的算法,你需要删除该行,或专门为它。

答案 2 :(得分:0)

你可以使用带有常量向量的lambda。 以你的例子:

vmap

或修改auto vmap(const F &f, V &v) ,它不需要常量向量。 以你的例子:

{{1}}