默认模板类lambda

时间:2019-03-08 04:56:44

标签: c++ templates lambda

让我们说您有一个模板函数,该函数需要一个“集合”,并且可能需要一个“转换” lambda:

template<typename Collection, typename Transform>
void DoIt(const Collection &c, Transform transform)
{
    for(auto &item: c)
    {
        std::cout << transform(item);
    }
}

但是我想要一个默认的lambda转换,该转换只是返回对其参数的引用。这样,如果Collection :: value_type支持<<到流中,则只需调用

DoIt(collection);

但如果没有,您可以致电:

DoIt(collection, [](const collection::value_type &item) { item.ToString();});

2 个答案:

答案 0 :(得分:4)

最简单的答案可能是重载该函数,然后调用另一个:

template<typename Collection, typename Transform>
void DoIt(const Collection &c, Transform transform)
{
    for(auto &item: c)
    {
        std::cout << transform(item);
    }
}

template<typename Collection>
void DoIt(const Collection &c)
{
    DoIt(c, [](auto &item) -> decltype(item) { return item; });
}

或者如果由于某种原因确实只需要一个模板,则需要一个类似函数的类,该类仅通过其参数传递。

namespace std_compat {
    struct identity
    {
        template<typename T>
        constexpr T&& operator()(T&& obj) const noexcept
        { return std::forward<T>(obj); }

        using is_transparent = void;
    };
}

template<typename Collection, typename Transform = std_compat::identity>
void DoIt(const Collection &c, Transform transform = {})
{
    for(auto &item: c)
    {
        std::cout << transform(item);
    }
}

这也允许用户执行类似DoIt<decltype(c), std::negate<>>(c);的操作。这似乎并不特别好或坏。

注意std::identity随C ++ 20一起提供。

答案 1 :(得分:2)

// Function object that returns a reference to x
struct SelfReference
{
    template<class T>
    auto operator()(T& x) const -> T&
    {
        return x;
    }
};

// default template argument selects SelfReference    
// also note default argument
template<typename Collection, typename Transform = SelfReference>
void DoIt(const Collection &c, Transform transform = Transform())
{
    for(auto &item: c)
    {
        std::cout << transform(item);
    }
}