Стандартный шаблон класса лямбда - PullRequest
1 голос
/ 08 марта 2019

Допустим, у вас есть шаблонная функция, которая принимает "коллекцию" и, возможно, "преобразование" лямбда-выражений:

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

Но я хочу преобразование лямбды по умолчанию, которое просто возвращает ссылку на его аргумент. Таким образом, если Collection :: value_type поддерживает << в потоки, вы можете просто вызвать </p>

DoIt(collection);

но если это не так, вы можете позвонить:

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

Ответы [ 2 ]

4 голосов
/ 08 марта 2019

Вероятно, самый простой ответ - перегрузить функцию и вызвать один вызов на другой:

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.

2 голосов
/ 08 марта 2019
// 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...