Я хочу створити 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
(я знаю, у цьому випадку це не може бути тип лямбда, але ви знаєте, я взагалі запитую)?
(Я використовую GCC, але хотів би знати, що взагалі роблять популярні компілятори)
РЕЗЮМЕ, ПІСЛЯ Я ОТРИМАВ БАГАТО ВЕЛИКИХ ВІДПОВІДЬ
Якщо швидкість є критичною, найкращим рішенням буде використання класу з operator()
ака-функтором. Компілятору найпростіше оптимізувати та уникнути будь-яких побічних дій.
Для зручності обслуговування та кращого рішення загального призначення, використовуючи функції C ++ 11, використовуйте std::function
. Це все ще швидко (лише трохи повільніше, ніж функтор, але може бути незначним), і ви можете використовувати будь-яку функцію - std::function
, лямбда, будь-який об’єкт, що викликається.
Також є можливість використовувати покажчик функції, але якщо проблеми зі швидкістю немає, я думаю, що std::function
це краще (якщо ви використовуєте C ++ 11).
Існує можливість визначити лямбда-функцію в іншому місці, але тоді ви нічого не отримуєте від функції порівняння, яка є лямбда-виразом, оскільки ви також можете зробити її класом operator()
а розташування визначення все одно не буде конструкцією набору.
Є більше ідей, таких як використання делегування. Якщо ви хочете отримати більш ретельне пояснення всіх рішень, прочитайте відповіді :)