为什么异常说明符在重载运算符'<

问题描述 投票:1回答:1

exemplo.cpp:

#include <type_traits>
using std::is_same;

#include <utility>
using std::declval;

#include <iostream>
using std::ostream;
using std::cout;

struct Foo final {
    int value;
    inline constexpr Foo(const int i) noexcept : value{i} {};
    inline ~Foo() = default;
};

ostream& operator<<(ostream& out, const Foo& foo) noexcept { return out << foo.value; }

int main() {
    const Foo a(42);
    static_assert(is_same<decltype(cout), ostream>::value == true, ""); // assert always to true...

    static_assert(noexcept(cout << a) == true, ""); // assert to true if the operator on line 21 is defined noexcept(true)

    static_assert(noexcept(declval<ostream>() << a) == true, ""); // assert always to false...

    static_assert(noexcept(declval<decltype(cout)>() << a) == true, ""); // Same as line 32...

    return 0;
}

编译命令:

g++ -std=c++2a -fconcepts exemplo.cpp -o exemp.run

错误:

exemplo.cpp:32:53: error: static assertion failed
    static_assert( noexcept( declval<ostream>() << a) == true, ""); // assert always to false...
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
exemplo.cpp:34:60: error: static assertion failed
    static_assert( noexcept( declval<decltype(cout)>() << a) == true, ""); // same as line 32
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~

'declval()'函数“生成给定类型的伪编译时对象”,即使这种类型不是真正可构造的。所以'declval()'应该生成另一个对象,比如std :: cout,其中第21行中的重载运算符应该在编译时工作(但它没有)。

我意识到这也适用于std :: clog和std :: cerr,它们都是ostream类型的变量。

它应该只是编译。我的意思是异常especifier应该对任何ostream对象都是一样的,不仅对这三个对象很明显。

注意:用G ++ 8.1.0编译;不需要图像上的标志。实际上,没有标志或只有标志-std = c ++ 11或更高可能会给出相同的输出。

c++11 constexpr noexcept
1个回答
0
投票

原因是declval生成一个临时对象,所以如果你的代码有另一个重载,就像这样

ostream& operator<<(ostream&& out, const Foo& foo) noexcept { return out << foo.value; }

它会工作。请注意,重载函数采用右值引用。我用gcc 4.8.5和-std=c++11测试了它。

© www.soinside.com 2019 - 2024. All rights reserved.