Прозрачные операторные функторы

Visual Studio 2013 Preview поддерживает функцию C++14, которая называется (согласно этой странице) "Прозрачные операторные функторы". Мне не ясно, что это значит. Ближайшее предложение C++14, которое я нашел, это, но я не уверен, что это то же самое: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421

Я ищу более четкое объяснение того, что это такое, почему это улучшение, и, возможно, фрагмент, демонстрирующий его использование.

1 ответ

Решение

Предложение о прозрачных операторных функторах существует как способ иметь обобщенные функторы, расположенные в <functional>, Я лично считаю, что само предложение имеет очень хороший пример, который поможет проиллюстрировать необходимость в нем. Однако я пойду дальше и попытаюсь это объяснить.

Предположим, у вас есть функция, очень простая функция:

template<typename T, typename U>
auto less_than(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)) {
    return std::forward<T>(t) < std::forward<U>(u);
}

Однако вы хотите использовать эту обобщенную функцию в <algorithm> заголовок. У вас есть два варианта, чтобы сделать его структурным функтором:

struct MyLessThanFunctor {
    template<typename T, typename U>
    auto operator()(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)){
        return std::forward<T>(t) < std::forward<U>(u);
    }
};

Или в C++14, чтобы сделать полиморфную лямбду:

[](auto&& t, auto&& u) -> decltype(auto) { 
    return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u); 
}

Оба очень многословны при использовании в алгоритме, например, так:

int main() {
    std::vector<int> v = {112,12,1281271,1919101,29181,412,1 };
    std::sort(std::begin(v), std::end(v), MyLessThanFunctor()); // one
    std::sort(std::begin(v), std::end(v), [](auto&& t, auto&& u) -> decltype(auto) { 
        return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u); 
    });
}

Это предложение направлено на то, чтобы сделать его более компактным и обобщенным, сделав вместо этого следующее:

std::sort(std::begin(v), std::end(v), std::less<>());

Это дает вам идеальную пересылку и решает проблемы с усечением или проблемы, возникающие из-за смены контейнера, но не базового типа, назначенного контейнером, как указано в документе.

Предположим, у вас есть не обобщенный функтор:

struct Functor {
    bool operator()(uint32_t a, uint32_t b) {
        return a < b;
    }
};

И вы используете это с вашим std::vector<uint32_t> и все работает нормально, но вы забываете, что ваш функтор не обобщается, и используете его со своими std::vector<uint64_t>, Вы видите проблему, которая возникла? Элементы будут усечены перед сравнением, что, вероятно, не то, что хотел пользователь. Обобщенные функторы решают эту проблему до того, как они возникнут.

Другие вопросы по тегам