Подтвердить что ты не робот

Как использовать выражение лямбда в качестве параметра шаблона?

Как использовать лямбда-выражение в качестве параметра шаблона? Например. как класс сравнения, инициализирующий std:: set.

Следующее решение должно работать, поскольку выражение лямбда просто создает анонимную структуру, которая должна быть подходящей в качестве параметра шаблона. Однако возникает множество ошибок.

Пример кода:

struct A {int x; int y;};
std::set <A, [](const A lhs, const A &rhs) ->bool {
    return lhs.x < rhs.x;
    } > SetOfA;

Выход ошибки (я использую компилятор g++ 4.5.1 и --std = С++ 0x флаг компиляции):

error: ‘lhs’ cannot appear in a constant-expression
error: ‘.’ cannot appear in a constant-expression
error: ‘rhs’ cannot appear in a constant-expression
error: ‘.’ cannot appear in a constant-expression
At global scope:
error: template argument 2 is invalid

Это ожидаемое поведение или ошибка в GCC?

ИЗМЕНИТЬ

Как заметил кто-то, я неправильно использую лямбда-выражения, поскольку они возвращают экземпляр анонимной структуры, на которую они ссылаются.

Однако исправление этой ошибки не решает проблему. Я получаю ошибку lambda-expression in unevaluated context для следующего кода:

struct A {int x; int y;};
typedef decltype ([](const A lhs, const A &rhs) ->bool {
    return lhs.x < rhs.x;
    }) Comp;
std::set <A, Comp > SetOfA;
4b9b3361

Ответ 1

Второй параметр шаблона std::set ожидает тип, а не выражение, так что вы просто используете его неправильно.

Вы можете создать набор следующим образом:

auto comp = [](const A& lhs, const A& rhs) -> bool { return lhs.x < rhs.x; };
auto SetOfA = std::set <A, decltype(comp)> (comp);

Ответ 2

Для компараторов, используемых таким образом, вам все же лучше с не-0x подход:

struct A { int x; int y; };

struct cmp_by_x {
  bool operator()(A const &a, A const &b) {
    return a.x < b.x;
  }
};

std::set<A, cmp_by_x> set_of_a;

Однако в 0x вы можете сделать cmp_by_x локальным типом (т.е. определить его внутри функции), когда это более удобно, что запрещено текущим С++.

Кроме того, ваше сравнение рассматривает A (x = 1, y = 1) и A (x = 1, y = 2) как эквивалентные. Если это нежелательно, вам нужно включить другие значения, которые способствуют уникальности:

struct cmp_by_x {
  bool operator()(A const &a, A const &b) {
    return a.x < b.x || (a.x == b.x && a.y < b.y);
  }
};

Ответ 3

Не уверен, что это то, о чем вы просите, но подпись lambda, которая возвращает RetType и принимает InType, будет:

std::function<RetType(InType)>

(Убедитесь, что #include <functional>)

Вы можете сократить это с помощью typedef, но я не уверен, что вы можете использовать decltype, чтобы избежать выяснения фактического типа (поскольку lambdas, по-видимому, не может использоваться в этом контексте.)

Итак, ваш typedef должен быть:

typedef std::function<bool(const A &lhs, const A &rhs)> Comp

или

using Comp = std::function<bool(const A &lhs, const A &rhs)>;

Ответ 4

проблема в последнем параметре шаблона - это не объект, поэтому вы можете сделать следующее

    std::set <A, std::fuction<bool(const A &,const A &)>> 
              SetOfA([](const A lhs, const A &rhs) ->bool {
                                                             return lhs.x < rhs.x;
                                                          } > SetOfA;

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

auto func = SetOfA([](const A lhs, const A &rhs) ->bool { return lhs.x < rhs.x;}
set <A,decltype(func)> SetOfA(func);

веселит