Struct keyword в функциональном параметре и const-correctness

У меня есть непрозрачный тип в моей библиотеке, который определяется как:

typedef struct MyOpaqueType* MyType; // easier to type for client code

Я не могу передать структуру указателя на const с использованием typedef, поэтому некоторые функции выглядят следующим образом:

void UsePointerToConst ( const struct MyOpaqueType * )

вместо:

void UserPointerToConst( const MyType ) // can't use, is really constant pointer

Итак, учитывая это, у меня есть два вопроса: Является ли ключевое слово struct в списке параметров только необходимым в C? Есть лучший способ сделать это? Должен ли я создать typedef, например:

typedef const struct MyOpaqueType* ConstantMyType; ?
3 ответа

Является ли ключевое слово struct в списке параметров только необходимым в C?

Да. См. ответ Йенса Густедта.

Есть ли лучший способ сделать это?

Просто typedef struct, а не указатель. Это лучше, потому что

  • вам нужен только один typedef вместо одного для каждого из {MyOpaqueType, MyOpaqueType *, MyOpaqueType const *, MyOpaqueType *const и MyOpaqueType const *const} и всех вариантов с участием restrict (которого нет в С++),
  • для пользователя ясно, что применяется семантика указателя, т.е. передача типа данных вокруг - это действительно вопрос копирования копий (без проблем с производительностью), пользователи с меньшей вероятностью забывают очистить после использования, пользователи С++ могут использовать интеллектуальные указатели, и
  • это общая конвенция C (подумайте FILE *).

Там также нет опасности; когда кто-то забывает *, они получают ошибку компилятора.


В С++ предполагается, что a typedef с тем же именем, что и struct, пока нет другого идентификатора с этим именем. Итак, что-то вроде функции stat, которая получает struct stat* в качестве аргумента:

int stat(const char *path, struct stat *buf);

разрешен даже в С++. (Это пример реального мира.)

Таким образом, вы всегда лучше с передовыми объявлениями вроде

typedef struct toto toto;

который резервирует токен toto в идентификаторе и в пространстве имен структуры. Затем вы можете объявить свой интерфейс функции для C и С++. Но не забывайте extern "C", если вы хотите получить к нему доступ также с C.

См. также: этот ответ на SO и теги структуры не являются идентификаторами в С++.


Вам не нужен typedef вообще на С++. Просто используйте объявление вперед:

struct MyType;

Затем переходите к MyType const *, MyType *, MyType const & и т.д., когда и когда это необходимо.

licensed under cc by-sa 3.0 with attribution.