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

Когда лямбда тривиальна?

Когда лямбда гарантирована быть тривиальной, если когда-либо?

Я предположил, что если он захватывает только тривиальные типы или ничего, это было бы тривиально. У меня нет никакого стандарта, чтобы поддержать это, хотя.

Моя мотивация заключалась в перемещении некоторого кода с Visual С++ с 12 по 14 и обнаружении каких-то статических утверждений не удалось при работе с лямбдами, которые я считал тривиальными.

Пример:

#include <type_traits>
#include <iostream>
using namespace std;

int main()
{
    auto lambda = [](){};

    cout << boolalpha << is_trivially_copyable<decltype(lambda)>{} << endl;
}

Это создает false в vs140, но true в vs120 и clang. Я не смог проверить gcc из-за отсутствия gcc >= 5. Я ожидаю, что это регресс в vs140, но я не уверен в правильном поведении здесь.

4b9b3361

Ответ 1

В стандарте не указывается, является ли тип замыкания (тип лямбда-выражения) тривиальным или нет. Он явно оставляет это до реализации, что делает его не переносным. Боюсь, вы не можете полагаться на свой static_assert, создающий что-либо согласованное.

Цитата С++ 14 (N4140) 5.1.2/3:

... Реализация может определять тип закрытия иначе, чем описано ниже, если это не изменяет наблюдаемые поведение программы кроме изменения:

  • размер и/или выравнивание типа закрытия,
  • разрешен ли тип закрытия тривиально (раздел 9),
  • является ли тип закрытия стандартным классом макета (раздел 9) или
  • является ли тип замыкания классом POD (раздел 9).

...

(Акцент мой)

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

Ответ 2

В соответствии с проектом стандарта N4527 5.1.2/3 Лямбда-выражения [expr.prim.lambda] (акцент мой):

Тип лямбда-выражения (который также является типом закрывающий объект) является уникальным, неназванным типом типа ununion, называемым тип закрытия - свойства которого описаны ниже. Этот тип класса не является ни агрегатом (8.5.1), ни буквальным типом (3.9). Закрытие тип объявляется в наименьшей области блока, классе или область пространства имен, которая содержит соответствующее лямбда-выражение. [ Примечание. Это определяет набор пространств имен и классов, связанных с типом замыкания (3.4.2). Типы параметров lambdadeclarator не влияет на эти связанные пространства имен и классы. - end note] Реализация может определять тип закрытия иначе, чем описано ниже, если это не изменит наблюдаемое поведение программы, отличное от изменения:

(3.1) - размер и/или выравнивание типа замыкания,

(3.2) - может ли тип замыкания тривиально скопирован (раздел 9),

(3.3) - независимо от того, тип закрытия - это класс стандартного макета (раздел 9) или

(3.4) - независимо от того, тип замыкания - класс POD (раздел 9).

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

Таким образом, он зависит от реализации.