Стандартно ли гарантировано, что лямбда без захвата будет пустой? - PullRequest
12 голосов
/ 27 января 2020

Я ищу способ идентифицировать пустые (без захвата) лямбды из других лямбд в функции шаблона. В настоящее время я использую C ++ 17, но мне также интересно узнать ответы на C ++ 20.

Мой код выглядит следующим образом:

template<typename T>
auto func(T lambda) {
    // The aguments of the lambdas are unknown

    if constexpr (/* is captureless */) {
        // do stuff
    }
}

Это гарантировано стандартом C ++ (17 или 20), что лямбда без захвата, которая может быть преобразована в указатель функции, также заставит std::is_empty привести к истине?

Взять этот код в качестве примера:

auto a = []{}; // captureless
auto b = [c = 'z']{}; // has captures

static_assert(sizeof(a) == sizeof(b)); // Both are the same size
static_assert(!std::is_empty_v<decltype(b)>); // It has a `c` member
static_assert(std::is_empty_v<decltype(a)>); // Passes. It is guaranteed?

Живой пример

1 Ответ

13 голосов
/ 27 января 2020

Нет, фактически, стандарт явно разрешает лямбдам иметь размер, который не соответствует их объявлению. [expr.prim.lambda.closure] / 2 состояния

Тип закрытия объявляется в наименьшей области блока, области класса или области пространства имен, которая содержит соответствующую лямбда- выражение. [Примечание: это определяет набор пространств имен и классов, связанных с типом замыкания ([basi c .lookup.argdep]). Типы параметров лямбда-объявления не влияют на эти связанные пространства имен и классы. - примечание конца] Тип закрытия не является агрегатным типом. Реализация может определять тип замыкания иначе, чем описано ниже, при условии, что это не изменяет наблюдаемое поведение программы, кроме как путем изменения:

  • размер и / или выравнивание типа закрытия,

  • независимо от того, является ли тип закрытия тривиально копируемым ([class.prop]), или (2.3)

  • , является ли тип замыкания классом стандартной компоновки ([class.prop]).

Реализация не должна добавлять члены ссылочного типа rvalue к типу замыкания.

выделение шахты

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

...