Я хочу создать std::set
с пользовательской функцией сравнения. Я мог бы определить его как класс с operator()
, но я хотел получить возможность определять лямбда, где он используется, поэтому я решил определить функцию лямбда в списке инициализации конструктора класса, который имеет std::set
как член. Но я не могу получить тип лямбды. Прежде чем продолжить, вот пример:
class Foo
{
private:
std::set<int, /*???*/> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
Я нашел два решения после поиска: один, используя std::function
. Просто установите тип функции сравнения std::function<bool (int, int)>
и передайте лямбду точно так, как я. Второе решение - написать функцию make_set, например std::make_pair
.
РЕШЕНИЕ 1:
class Foo
{
private:
std::set<int, std::function<bool (int, int)> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
РЕШЕНИЕ 2:
template <class Key, class Compare>
std::set<Key, Compare> make_set (Compare compare)
{
return std::set<Key, Compare> (compare);
}
Вопрос в том, есть ли у меня веская причина предпочесть одно решение другому? Я предпочитаю первый, потому что он использует стандартные функции (make_set - не стандартная функция), но мне интересно: использует ли std::function
код (потенциально) медленнее? Я имею в виду, снижает ли вероятность того, что компилятор включит функцию сравнения, или он должен быть достаточно умным, чтобы вести себя точно так же, как если бы это был тип функции лямбда, а не std::function
(я знаю, в этом случае он может " t быть лямбда-типом, но знаете, я спрашиваю вообще)?
(Я использую GCC, но я хотел бы знать, что делают популярные компиляторы вообще)
АННОТАЦИЯ, ПОСЛЕ У ДЕТЕЙ БОЛЬШИХ ОТВЕТОВ:
Если скорость критическая, лучшим решением является использование класса с operator()
aka functor. Легче всего компилятор оптимизировать и избежать любых указаний.
Для удобства обслуживания и лучшего универсального решения, используя возможности С++ 11, используйте std::function
. Он по-прежнему быстрый (немного медленнее, чем функтор, но он может быть незначительным), и вы можете использовать любую функцию - std::function
, лямбда, любой вызываемый объект.
Также есть возможность использовать указатель на функцию, но если нет проблемы с производительностью, я думаю, что std::function
лучше (если вы используете С++ 11).
Здесь есть возможность определить функцию лямбда где-то еще, но тогда вы ничего не получаете от функции сравнения, являющейся выражением лямбда, так как вы могли бы также сделать ее классом с operator()
, а местоположение определения не было бы все равно построенная конструкция.
Есть больше идей, например, использование делегирования. Если вы хотите более подробное объяснение всех решений, прочитайте ответы:)