Копировать исключение возвращаемых значений и noexcept

Martin Kalbfuß спросил: 28 марта 2018 в 01:47 в: c++

У меня есть шаблон функции, подобный этому:

template <typename T>
constexpr auto myfunc() noexcept
{
    return T{};
}

Является ли этот шаблон функции гарантией того, что это не исключено из-за копирования? Если исключение выбрано внутри конструктора, это происходит внутри или вне функции?

2 ответа

Есть решение
Sam Varshavchik ответил: 28 марта 2018 в 01:56

Все, что делает elision copy, - это исключает фактическую копию или перемещение. Все происходит так, как будто все происходит без исключения копирования (конечно, за исключением самой копии).

Построение происходит внутри функции. Копия elision не меняет этого. Все, что он делает - это исключает фактическое копирование / перемещение (я повторяюсь?) В результате возврата возвращаемого значения функции обратно в вызывающую функцию.

Итак, если класс Конструктор default выдает исключение, noexcept обнуляет все это с высокой орбиты.

Если конструктор копирования / перемещения выдает исключение, так как копирование / перемещение не происходит, все продолжает идти вперед.

С gcc 7.3.1, скомпилированным с использованием -std = c ++ 17:

template <typename T>
constexpr auto myfunc() noexcept
{
    return T{};
}class xx {
public:    xx() { throw "Foo"; }
};int main()
{
    try {
        myfunc<xx>();
    } catch (...) {
    }
}

Результат:

terminate called after throwing an instance of 'char const*'

Теперь давайте смешаем его и сгенерируем исключение в конструкторах копирования и перемещения:

class xx {
public:    xx() { }    xx(xx &&) { throw "Foo"; }    xx(const xx &) { throw "Baz"; }
};

Это работает без исключения.

Jive Dadson ответил: 28 марта 2018 в 02:41

Сделайте это так:

template <typename T> constexpr 
auto myfunc() noexcept(std::is_nothrow_default_constructible_v<T>)
{
    return T{};
}