Я смотрел этот пост, когда вижу эту строку.
Короче говоря, код выглядит так:
struct cell {
typedef cell (*proc_type)(const std::vector<cell> &);
typedef std::vector<cell>::const_iterator iter;
typedef std::map<std::string, cell> map;
cell_type type;
std::string val;
std::vector<cell> list;
proc_type proc;
environment * env;
cell(cell_type type = Symbol) : type(type), env(0) {}
cell(cell_type type, const std::string & val) : type(type), val(val), env(0) {}
cell(proc_type proc) : type(Proc), proc(proc), env(0) {}
};
Итак, что делает typedef cell (* proc_type) (const std :: vector &); делать?
Предполагается, что typedef будет использоваться как
typedef (existing) (new)
Итак, почему объявление такого сложного нового типа, когда мы могли бы просто использовать ячейку вместо этого?
Ваше утверждение о том, что "typedef предполагается использовать как typedef (existing) (new)
", совершенно неверно. Нет, в общем случае он не будет использоваться так. В этом формате могут следовать только самые основные объявления typedef.
Синтаксис объявления typedef в C (или C++) основан на синтаксисе обычной декларации. Фактически, это точно такой же синтаксис, что и ключевое слово typedef
. На этих языках декларация не может быть четко разделена на две части, как вы пытались сделать в своем случае. Синтаксис декларации намного сложнее. Заявленное имя обычно находится в середине токенов, которые описывают тип этого имени.
Для простого примера объявление для объекта с именем a
типа массива int [10]
будет выглядеть следующим образом
int a[10];
Он имеет части слева от имени (int
) и справа от имени ([10]
). Аналогично, в объявлении typedef токены, которые описывают тип, могут (и будут) находиться слева и справа от нового типа. В вашем примере
typedef cell (*proc_type)(const std::vector<cell> &);
новое имя proc_type
объявляется, а все, что его окружает с обеих сторон, фактически описывает тип cell (*)(const std::vector<cell> &)
это новое имя typedef будет означать. Это тип указателя: указатель на функцию, который получает const std::vector<cell> &
parameter и возвращает значение cell
.
Вы можете вывести сложные typedefs, такие как указатели на функции, вставив их в онлайн-сайт cdecl:
Или, используя правило "право-слева":
Итак, что делает typedef cell (* proc_type) (const std :: vector &); делать?
Он объявляет новый тип с именем proc_type
который является указателем на функцию, использующую соглашение о вызове по умолчанию для компилятора (обычно __cdecl
), принимает значение const std::vector<cell> &
as и возвращает cell
.
Код за пределами того, что вы показали, затем назначит функцию cell::proc
, по-видимому, так, чтобы пользователи cell
сети могли впоследствии вызвать эту функцию, когда это необходимо, не зная или не заботясь о том, какая функция фактически вызывается (в коде, к которому вы ссылаетесь, эти функции назначаются в add_globals()
через конструктор cell(proc_type)
).
Классический сценарий обратного вызова.
typedef cell (*proc_type)(const std::vector &);
определяет proc_type
как cell (*)(const std::vector&)
типа указателя функции cell (*)(const std::vector&)
<type> <name>;
формат. Однако это не так в общем случае. Точнее, любые объявления, которые напрямую связаны с типами массивов и типами функций, не будут следовать этому формату. Как только вы начнете работать с массивами и типами функций, вы заметите, что тип «дескриптор» оборачивается вокруг имени, объявленного с обеих сторон (слева и справа)