Конструктор неявного перемещения должен быть по возможности без исключения.

В основном по стандарту:

Конструктор-наследник (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

Что-то мне не хватает?


person Quest    schedule 11.05.2020    source источник


Ответы (1)


Что-то мне не хватает?

да. const

Член Foo::stringField не std::string, это const std::string. const std::string не является конструктивным элементом перемещения без перемещения 1, и, следовательно, конструктор неявного перемещения для Foo не является ни тем, ни другим.

1 Const rvalue не может привязаться к неконстантной ссылке rvalue, поэтому конструктор перемещения не будет использоваться. Вместо этого используется конструктор копирования, и конструктор копирования std::string потенциально выбрасывает.

person eerorika    schedule 11.05.2020