Является ли признак C ++ is_lambda, чисто реализованный в виде библиотеки, невозможным? - PullRequest
9 голосов
/ 11 января 2011

У меня вопрос по поводу C ++ 0x лямбда-выражений.В моем коде было бы полезно узнать, является ли данный тип типом лямбда-выражения C ++ 0x.Для примера:

struct foobar
{
  void operator()()
  {
  }
};

auto lambda = []{};
typedef is_lambda < decltype(lambda) > ::type T; // T would be a true_type
typedef is_lambda < foobar > ::type T; // T would be a false_type

Довольно легко отличить лямбда-выражения от типов функций и функций-членов.Функторы - это другое дело.

Проблема, которую я вижу здесь, заключается в определении лямбда-выражений в соответствии с готовящимся стандартом C ++ 0x;единственное, что должно быть определено, это оператор публичного вызова.Однако это верно и для функтора;проверки на наличие оператора вызова недостаточно для различения лямбда-выражений от функторов.Кроме того, если оператор функтора отсутствует , то произойдет ошибка компилятора, поскольку SFINAE не применяется.Когда это происходит?Оператор вызова функтора может быть шаблонным.Таким образом, такой код:

typedef decltype(&T::operator()) call_type;

будет работать как для лямбда-выражений, так и для функторов с не шаблонным оператором вызова и генерировать ошибку компилятора для операторов шаблонного вызова.1013 * черта может быть создана только с использованием встроенных функций компилятора.Вы видите способ реализации этой черты?

Ответы [ 3 ]

8 голосов
/ 11 января 2011

Поскольку оценка лямбды приводит к созданию объекта замыкания, нет никакой разницы, как только объект передается в функцию или копируется. И, честно говоря, я не могу представить себе проблему, которая потребовала бы выяснения, произошел ли объект от лямбды.

Edit. Стандарт даже имеет примечание в 5.1.2 / 2:

Примечание: закрывающий объект ведет себя как функциональный объект (20.8) .— конец примечания

6 голосов
/ 11 января 2011

Я не верю, что это можно сделать - лямбды на самом деле не являются чем-то новым семантически, они просто генерируемые компилятором функторы и, следовательно, будут выглядеть как обычные функторы.

1 голос
/ 29 марта 2014

Можно определить некоторый макрос-код, который определяет, является ли выражение лямбда выражением (но это не очень полезно, так как не сообщает вам, является ли выражение лямбда типа ).

#include <type_traits>

template<typename T, typename U>
struct SameType {
    static_assert(!std::is_same<T, U>::value, "Must use Lambda");
    static T pass(T t) { return t; }
};

template <typename T, typename U>
T NotLambda(T t, U u) { return SameType<T, U>::pass(t); }

#define ASSERT_LAMBDA(x) NotLambda(x,x)

/////////////////////////////////////

int fn() { return 0; }

int main() {
    auto l = []{ return 0; };
    return ASSERT_LAMBDA(fn)() +             // << fails
           ASSERT_LAMBDA(l)() +              // << fails
           ASSERT_LAMBDA([]{ return 0; })(); // << passes
}

Это зависит от раздела 5.1.2.3, в котором указано, что каждое лямбда-выражение имеет отдельный тип (который, я думаю, является свойством, уникальным для лямбда-выражений).

...