copy elision of return values and noexcept

江枫思渺然 提交于 2020-05-29 03:58:19

问题


I have a function template like this:

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

Is this function template guaranteed to be noexcept because of copy elision? If an exception is thrown inside the constructor, does this happen inside or outside the function?


回答1:


All that copy elision does is eliminate the actual copy or move. Everything happens "as-if" things happen without the copy-elision taking place (except for the copy itself, of course).

The construction occurs inside the function. Copy elision does not change that. All it does is eliminate the actual copy/move from taking place (am I repeating myself?) as the result of the function's return value getting shoved back into its caller.

So, if the class's default constructor throws an exception, the noexcept nukes the whole thing from high orbit.

If the copy/move constructor throws an exception, since the copy/move does not happen, everything continues to chug along.

With gcc 7.3.1, compiled using -std=c++17:

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

class xx {
public:

    xx() { throw "Foo"; }
};

int main()
{
    try {
        myfunc<xx>();
    } catch (...) {
    }
}

The result:

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

Now, let's mix it up, and throw an exception in both copy and move constructors:

class xx {
public:

    xx() { }

    xx(xx &&) { throw "Foo"; }

    xx(const xx &) { throw "Baz"; }
};

This runs without an exception.




回答2:


Do it like this:

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


来源:https://stackoverflow.com/questions/49957330/copy-elision-of-return-values-and-noexcept

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!