Является ли по умолчанию конструктором/присваиванием noexcept/constexpr по умолчанию?

Итак, мой вопрос прост:

Есть ли смысл в определении конструктора класса дефолта в noexcept или constexpr (или любая другая вещь вы могли бы вещь)?

struct foo
{
   foo() = default;
   // vs
   constexpr foo() noexcept = default;

   // same thing would apply for copy/move ctors and assignment operators
};

Будут ли два поведения одинаковыми?

Это зависит от того, является ли класс POD? Например, в приведенном выше примере оба будут вести себя одинаково, тогда как если бы у меня был частный член std::vector<int> v = { 1, 2, 3, 4 }; который использует назначение класса, foo() = default; по умолчанию не будет noexcept и не constexpr.

Написав foo() = default; компилятор просто выбирает лучшую версию: noexcept если это возможно, и constexpr если это возможно, и т.д.?

Ответ 1

[dcl.fct.def.default]/2-3:

2 Явно-дефолтная функция, которая не определена как удаленная, может быть объявлена constexpr только в том случае, если она была бы неявно объявлена как constexpr. Если в первом объявлении функция явно дефолтована,

  • он неявно считается constexpr если подразумевается декларация, и,
  • он имеет такую же спецификацию исключения, как если бы он был неявно объявлен ([except.spec]).

3 Если функция, явно заданная по умолчанию, объявляется с несобственной спецификацией исключения ([except.spec]) с спецификацией исключения неявного объявления, тогда

  • если функция явно дефолтована по первому объявлению, она определяется как удаленная;

  • в противном случае программа плохо сформирована.

Другими словами, foo() = default; , который обязательно является первым объявлением конструктора по умолчанию foo, будет " constexpr по возможности" и " noexcept если это возможно". Явное написание constexpr и noexcept еще полезна; это означает "кричать на меня, если это не может быть constexpr/noexcept ".