Visual Studio 2013 Preview поддерживает функцию C ++ 14, называемую этот страница) «Прозрачные операторные функторы». Мне не ясно, что это значит. Ближайшее предложение C ++ 14, которое я нашел, это, но я не уверен, что это то же самое:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421
Я ищу более четкое объяснение того, что это такое, почему это улучшение, и, возможно, фрагмент, демонстрирующий его использование.
Предложение о прозрачных операторных функторах существует как способ иметь обобщенные функторы, расположенные в <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>
, Вы видите проблему, которая возникла? Элементы будут усечены перед сравнением, что, вероятно, не то, что хотел пользователь. Обобщенные функторы решают эту проблему за вас до того, как они возникнут.
Других решений пока нет …