Смысл явного дублирования имени класса через typedef
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.06.21 11:32
Оценка:
В виндовых SDK/WDK, включая последние десяточные, полно конструкций такого вида:

#ifdef __cplusplus
typedef class Xxx Xxx;
#else
typedef struct Xxx Xxx;
#endif /* __cplusplus */

В альтернативной части безусловно есть смысл, а в основной? В каких случаях имя класса в C++ может не являться именем типа?
microsoft имя класса типа
Re: Смысл явного дублирования имени класса через typedef
От: SaZ  
Дата: 29.06.21 11:59
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>В виндовых SDK/WDK, включая последние десяточные, полно конструкций такого вида:


ЕМ>#ifdef __cplusplus

ЕМ>typedef class Xxx Xxx;
ЕМ>#else
ЕМ>typedef struct Xxx Xxx;
ЕМ>#endif /* __cplusplus */

ЕМ>В альтернативной части безусловно есть смысл, а в основной? В каких случаях имя класса в C++ может не являться именем типа?


Это скорее всего сделано для совместимости с Си.
Re: Смысл явного дублирования имени класса через typedef
От: night beast СССР  
Дата: 29.06.21 12:05
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>В альтернативной части безусловно есть смысл, а в основной? В каких случаях имя класса в C++ может не являться именем типа?


форвард декларации с плюсах никуда не делись
void foo(class XXX&);
Отредактировано 29.06.2021 13:38 night beast . Предыдущая версия .
Re[2]: Смысл явного дублирования имени класса через typedef
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.06.21 12:21
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Это скорее всего сделано для совместимости с Си.


Для совместимости с C там альтернативная часть. Для чего основная?
Re[2]: Смысл явного дублирования имени класса через typedef
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.06.21 12:22
Оценка:
Здравствуйте, night beast, Вы писали:

NB>форвард декларации с плюсах никуда не делись


Как это относится к заданному вопросу?
Re[3]: Смысл явного дублирования имени класса через typedef
От: night beast СССР  
Дата: 29.06.21 12:29
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

NB>>форвард декларации с плюсах никуда не делись


ЕМ>Как это относится к заданному вопросу?


попробуй в примере убрать class и поймешь
Re[4]: Смысл явного дублирования имени класса через typedef
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.06.21 17:17
Оценка:
Здравствуйте, night beast, Вы писали:

NB>попробуй в примере убрать class и поймешь


А, вот Вы о чем... А чем это лучше обычной опережающей декларации имени класса?
Re[5]: Смысл явного дублирования имени класса через typedef
От: night beast СССР  
Дата: 29.06.21 18:32
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

NB>>попробуй в примере убрать class и поймешь


ЕМ>А, вот Вы о чем... А чем это лучше обычной опережающей декларации имени класса?


да в общем то, ничем, наверное
а чем хуже?
Re[6]: Смысл явного дублирования имени класса через typedef
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.06.21 18:39
Оценка:
Здравствуйте, night beast, Вы писали:

NB>а чем хуже?


Значительно длиннее, смысл неясен, в отличие от.
Re: Смысл явного дублирования имени класса через typedef
От: Quebecois Канада https://www.canada.ca/
Дата: 29.06.21 18:52
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>В виндовых SDK/WDK, включая последние десяточные, полно конструкций такого вида:


ЕМ>#ifdef __cplusplus

ЕМ>typedef class Xxx Xxx;
ЕМ>#else
ЕМ>typedef struct Xxx Xxx;
ЕМ>#endif /* __cplusplus */

ЕМ>В альтернативной части безусловно есть смысл, а в основной? В каких случаях имя класса в C++ может не являться именем типа?

Дело может быть в порядке, в котором компилятор будет перебирать разные вещи, увидев в коде ссылку на Xxx. Т.е. сначала попытается найти локальную переменную, потом глобальную, потом подтянет using, потом явные typedefs, потом классы и структуры. Если между двумя последними пунктами есть что-то еще, то явный typedef повысит приоритет Xxx относительно этого чего-то.

Но не стоит исключать вариант, что это просто необдуманная копипаста в процессе исправления срочного бага.
Re[2]: Смысл явного дублирования имени класса через typedef
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.06.21 19:16
Оценка:
Здравствуйте, Quebecois, Вы писали:

Q>Дело может быть в порядке, в котором компилятор будет перебирать разные вещи, увидев в коде ссылку на Xxx. Т.е. сначала попытается найти локальную переменную, потом глобальную


Зачем ему искать переменные, когда Xxx используется, как имя типа?

Q>потом подтянет using, потом явные typedefs, потом классы и структуры. Если между двумя последними пунктами есть что-то еще, то явный typedef повысит приоритет Xxx относительно этого чего-то.


Разве промышленные компиляторы занимаются прямым перебором? Они должны иметь индексы на каждую категорию языковых объектов.

Q>Но не стоит исключать вариант, что это просто необдуманная копипаста в процессе исправления срочного бага.


Там таких typedef'ов 100500.
Re[3]: Смысл явного дублирования имени класса через typedef
От: Quebecois Канада https://www.canada.ca/
Дата: 29.06.21 19:35
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Зачем ему искать переменные, когда Xxx используется, как имя типа?

Потому что какой-то другой кусок кода где-то объявит Xxx по-другому, и тогда приоритет станет важен.

ЕМ>Разве промышленные компиляторы занимаются прямым перебором? Они должны иметь индексы на каждую категорию языковых объектов.

Я не говорю о скорости перебора. Я имел в виду результат компиляции.

ЕМ>Там таких typedef'ов 100500.

Которые могут генерироваться одной внутренней программой. Или быть описанными в guidelines, куда были скопированы из кривого фикса.
Re: Смысл явного дублирования имени класса через typedef
От: watchmaker  
Дата: 29.06.21 19:46
Оценка: 50 (9) +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ> В каких случаях имя класса в C++ может не являться именем типа?


Разумеется в случае, когда это имя является именем чего-то другого. Например, именем функции:
#if 1
class foo;
#else
typedef class foo foo;
#endif

const char* foo() {
    return "fn";
}


Демо: https://godbolt.org/z/c31vh54xv — если не использовать typedef, то программа компилируется, но её поведение кардинально меняется от наличия объявления функции (второй define примера). И такое объявление функции в реальности будет не лежать рядом с классом, а приедет через пять транзитивных #include из какой-то другой библиотеки.

А typedef позволяет получить ошибку компиляции вместо ошибки во время исполнения программы.
Отредактировано 29.06.2021 20:42 watchmaker . Предыдущая версия . Еще …
Отредактировано 29.06.2021 20:34 watchmaker . Предыдущая версия .
Отредактировано 29.06.2021 20:33 watchmaker . Предыдущая версия .
Re[2]: Смысл явного дублирования имени класса через typedef
От: Skorodum Россия  
Дата: 02.07.21 07:56
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Демо: https://godbolt.org/z/c31vh54xv


Спасибо, полезно.
Вроде бы class в параметре функции должен дать понять компилятору, что мы хотим экземпляр класса, а не функцию, почему это не работает?

const char* foo() {
    return "fn";
}

class foo {
};

std::ostream& operator<<(std::ostream& os, const class foo&) {
    os << "cl";
    return os;
}


И если убрать class из параметра функции, то clang дает очень вменяемое сообщение об ошибке

<source>:21:50: error: must use 'class' tag to refer to type 'foo' in this scope
std::ostream& operator<<(std::ostream& os, const foo&) {
^
class
<source>:13:13: note: class 'foo' is hidden by a non-type declaration of 'foo' here
const char* foo() {
^
1 error generated.


Пока выглядит что проблема тут только при использовании class c параметром
Re[3]: Смысл явного дублирования имени класса через typedef
От: watchmaker  
Дата: 02.07.21 08:42
Оценка: 17 (2)
Здравствуйте, Skorodum, Вы писали:

S>Вроде бы class в параметре функции должен дать понять компилятору, что мы хотим экземпляр класса, а не функцию, почему это не работает?


В параметре функции std::ostream& operator<<? Там отлично работает.
Дело-то в том, что эта функция потом не вызывается.


S>И если убрать class из параметра функции, то clang дает очень вменяемое сообщение об ошибке

S>Пока выглядит что проблема тут только при использовании class c параметром

Вообще, const class foo& — это артефакт примера из-за того, что я зачем-то всунул определение функции в середину исходника. Можно легко переписать без него просто поменяв строки местами и получить тот же эффект.

// lib_a.h
#pragma once
// declarations
class foo {};
std::ostream& operator<<(std::ostream& os, const foo&);


// lib_b.h
#pragma once
// declarations
const char* foo();


Тогда если сделать в программе include в неудачном порядке, то получится то же самое:
#include <lib_a.h>
#include <lib_b.h>

...

auto f = foo(); // — это вызов конструктора класса или свободной функции? Зависит от наличия include
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.