Я хочу створити 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() а розташування визначення все одно не буде конструкцією набору.
Є більше ідей, таких як використання делегування. Якщо ви хочете отримати більш ретельне пояснення всіх рішень, прочитайте відповіді :)