Дивна мова - CWG 1581 :
Пункт 15 [спеціальний] цілком зрозуміло, що функції спеціальних членів визначаються лише неявно під час їх використання. Це створює проблему для постійних виразів у неоцінених контекстах:
struct duration {
constexpr duration() {}
constexpr operator int() const { return 0; }
};
// duration d = duration(); // #1
int n = sizeof(short{duration(duration())});
Проблема тут полягає в тому, що нам не дозволяється неявно визначати constexpr duration::duration(duration&&)
в цій програмі, тому вираз у списку ініціалізатора не є постійним виразом (тому що він викликає функцію constexpr, яка не була визначена), тому скобований ініціалізатор містить конверсію звуження , тому програма неправильно сформована.
Якщо ми відмежуємо рядок №1, конструктор переміщення неявно визначений, а програма дійсна. Ця моторошна дія на відстані вкрай прикро. З цього приводу розбіжності розходяться.
Ви можете прочитати решту опису випуску.
Розв’язання цього питання було прийнято в P0859 в Альбукерке в 2017 році (після відправки C ++ 17). Це питання було блокатором як для можливості constexpr std::swap
(вирішено в P0879 ), так і для constexpr std::invoke
(вирішено в P1065 , який також має приклади CWG1581), як для C ++ 20.
Найпростіший для розуміння приклад, на мою думку, - це код із звіту про помилки LLVM, зазначений у P1065:
template<typename T>
int f(T x)
{
return x.get();
}
template<typename T>
constexpr int g(T x)
{
return x.get();
}
int main() {
// O.K. The body of `f' is not required.
decltype(f(0)) a;
// Seems to instantiate the body of `g'
// and results in an error.
decltype(g(0)) b;
return 0;
}
CWG1581 - це все, коли визначено функції члена constexpr, і роздільна здатність гарантує, що вони визначені лише при використанні. Після P0859 зазначене вище добре сформоване (тип b
єint
).
Оскільки std::swap
і std::invoke
обидва повинні покладатися на перевірку функцій членів (переміщення конструкції / призначення в першому та оператора викликів / сурогатних викликів в другому), вони обоє залежали від вирішення цього питання.