Должны ли неоцененные операнды иметь допустимые определения?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Должны ли неоцененные операнды иметь допустимые определения?

Сообщение Anonymous »

Основные реализации C++, похоже, имеют совершенно иное
представление по этому поводу. Что делать с обоснованностью следующих 4
утверждений?
struct a {
template
constexpr a() { (T&&)0; }
};
struct b : a {};

template
constexpr int f() { return (T&&)0; }

template
constexpr int v = (T&&)0;

static_assert(sizeof(b{})); // #1 - clang nope, gcc ok, msvc ok
static_assert(sizeof(a{})); // #2 - clang ok, gcc nope, msvc ok
static_assert(sizeof(f())); // #3 - clang ok, gcc nope, msvc ok
static_assert(sizeof(v)); // #4 - clang ok, gcc ok, msvc nope

Очевидно, что формирование ссылки на void (т.е. (T&&)0, где T = void)
не является допустимым выражением. Однако такое выражение на самом деле никогда
не вычисляется в этом примере программы, поскольку оно является лишь частью
определения невычисленного операнда. Чем на самом деле объясняется такое
расхождение в поведении всех этих компиляторов?
Демо

Ошибка Clang сообщение:
:3:23: error: cannot form a reference to 'void'
3 | constexpr a() { (T&&)0; }
| ^
:13:24: note: in instantiation of function template specialization
'a::a' requested here
13 | static_assert(sizeof(b{}));
| ^
:14:22: error: no matching constructor for initialization of 'a'
14 | static_assert(sizeof(a{}));
| ^~~
:3:15: note: candidate template ignored: substitution failure
[with T = void]
3 | constexpr a() { (T&&)0; }
| ^
:1:8: note: candidate constructor (the implicit copy constructor)
not viable: requires 1 argument, but 0 were provided
1 | struct a {
| ^
:1:8: note: candidate constructor (the implicit move constructor)
not viable: requires 1 argument, but 0 were provided
1 | struct a {
| ^

Сообщение об ошибке GCC:
: In instantiation of 'constexpr a::a() [with T = void]':
:14:24: required from here
14 | static_assert(sizeof(a{}));
| ^
:3:21: error: forming reference to void
3 | constexpr a() { (T&&)0; }
| ^~~~~~
: In instantiation of 'constexpr int f() [with T = void]':
:15:23: required from here
15 | static_assert(sizeof(f()));
| ~~^~~
:8:28: error: forming reference to void
8 | constexpr int f() { return (T&&)0; }
| ^~~~~~

Сообщение об ошибке MSVC:
(11): error C7683: you cannot create a reference to 'void'
(11): note: the template instantiation context (the oldest one first) is
(16): note: see reference to variable template 'const int v'
being compiled


Подробнее здесь: https://stackoverflow.com/questions/792 ... defintions
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»