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.
Это должно просто скомпилироваться. Я имею в виду, что спецификатор исключения должен быть одинаковым для любого объекта ostream, не только для этих трех, очевидно.
Примечание: компиляция с G ++ 8.1.0; флаги на изображении не нужны. На самом деле, ни один флаг, или только флаг -std = c ++ 11 или выше, не может дать такой же вывод.