В основном по стандарту:
Конструктор-наследник (12.9) и неявно объявленная специальная функция-член (раздел 12) имеют спецификацию исключения. Если
f
является наследующим конструктором или неявно объявленным конструктором по умолчанию, конструктором копирования, конструктором перемещения, деструктором, оператором присваивания копии или оператором присваивания перемещения, его неявная спецификация исключения указывает идентификатор типаT
тогда и только тогда, когдаT
разрешено спецификацией исключения функции, непосредственно вызываемой неявным определениемf
;f
разрешает все исключения, если любая функция, которую он непосредственно вызывает, разрешает все исключения, аf
имеет спецификацию исключенияnoexcept(true)
, если каждая функция, которую он непосредственно вызывает, не допускает исключений.
Следовательно, следующий фрагмент кода должен иметь неявный конструктор перемещения noexcept:
template<typename _Tp>
class Foo
{
public:
Foo() = default;
explicit Foo(const std::string& s, const std::function<bool(_Tp&)>& f) : stringField(s), funcField(f) {}
private:
const std::string stringField;
std::function<bool(_Tp&)> funcField;
};
но, к сожалению, это не так:
int main()
{
std::cout << "std::string: " << std::is_nothrow_move_constructible_v<std::string> << std::endl;
std::cout << "std::function: " << std::is_nothrow_move_constructible_v<std::function<bool(std::string&)>> << std::endl;
std::cout << "string_t: " << std::is_nothrow_move_constructible_v<Foo<std::string>> << std::endl;
return 0;
}
отпечатки
std::string: 1
std::function: 1
string_t: 0
с использованием g ++ 8.3.0 в Ubuntu 18.04 LTS
Что-то мне не хватает?