Когда лямбда тривиальна?
Когда лямбда гарантирована быть тривиальной, если когда-либо?
Я предположил, что если он захватывает только тривиальные типы или ничего, это было бы тривиально. У меня нет никакого стандарта, чтобы поддержать это, хотя.
Моя мотивация заключалась в перемещении некоторого кода с 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, но я не уверен в правильном поведении здесь.
Ответы
Ответ 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 к типу закрытия
Таким образом, он зависит от реализации.