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或更高可能会给出相同的输出。
原因是declval
生成一个临时对象,所以如果你的代码有另一个重载,就像这样
ostream& operator<<(ostream&& out, const Foo& foo) noexcept { return out << foo.value; }
它会工作。请注意,重载函数采用右值引用。我用gcc 4.8.5和-std=c++11
测试了它。