Определение типа функции (НЕ указатель на функцию)

typedef void int_void(int);

int_void — это функция, принимающая целое число и ничего не возвращающая.

У меня вопрос: можно ли его использовать "самостоятельно", без указателя? То есть можно ли использовать его просто как int_void, а не int_void*?

typedef void int_void(int);
int_void test;

Этот код компилируется. А можно ли test как-то использовать или присвоить что-то (без приведения)?


/* Even this does not work (error: assignment of function) */
typedef void int_void(int);
int_void test, test2;
test = test2;

person Thomas Bonini    schedule 19.02.2010    source источник
comment
Вы пробовали на самом деле скомпилировать что-то подобное? Если да, то каковы были результаты? Каков был фактический исходный код?   -  person FrustratedWithFormsDesigner    schedule 19.02.2010
comment
Как я сказал в вопросе, он компилируется. Фактический исходный код таков. Просто заверните его в int main().   -  person Thomas Bonini    schedule 19.02.2010
comment
Обратите внимание, что существует ограничение того, что можно сделать с таким типом. Вам не разрешено использовать зависимый тип для объявления функции, в котором не используется синтаксис декларатора функции: template<typename T> struct f { T g; } ... f<void()> s; это неправильно, а не объявление функции-члена типа void(), потому что T является зависимым типом функции.   -  person Johannes Schaub - litb    schedule 19.02.2010


Ответы (6)


Что происходит, так это то, что вы получаете более короткое объявление для функций.

Вы можете вызвать test, но вам понадобится фактическая функция test().

Вы не можете ничего назначить для проверки, потому что это метка, по сути, постоянное значение.

Вы также можете использовать int_void для определения указателя функции, как показывает Нейл.


Пример

typedef void int_void(int);

int main()
{
    int_void test; /* Forward declaration of test, equivalent to:
                    * void test(int); */
    test(5);
}

void test(int abc)
{
}
person Community    schedule 19.02.2010
comment
Спасибо! Это действительно крутой способ запутать людей! Я добавил тестовый пример, который написал, чтобы убедиться, что то, что вы сказали, действительно работает, надеюсь, вы не возражаете - person Thomas Bonini; 19.02.2010
comment
Нет, спасибо. Увы, я не могу понять, как использовать его для самой функции. Было бы здорово иметь возможность, например. pthread_entryfn a { - person ; 19.02.2010
comment
Следует отметить, что typedef может использоваться для объявления функции, но не может использоваться для определения функции, поэтому в приведенном выше примере объявление test и определение не похожи друг на друга. Насколько мне известно, все остальные имена typedef можно использовать как для объявления, так и для определения. - person Michael Burr; 19.02.2010
comment
@Andreas, не только это может сбить с толку людей, но и GCC: попробуйте struct foo { void f(); }; typedef void ftype(); struct bar { friend ftype foo::f; }; и увидите, что GCC не работает. - person Johannes Schaub - litb; 19.02.2010
comment
@Johannes: +1, хотя если бы у нас был +1 за каждую ошибку gcc, мы все были бы богами модераторов .. ;-) - person R.. GitHub STOP HELPING ICE; 19.10.2010
comment
В частности, вы можете использовать его для шаблона функции: template<typename T> int_void test; - person Johannes Schaub - litb; 19.10.2010

Вы не объявляете переменную; вы делаете предварительное объявление функции.

typedef void int_void(int);
int_void test;

эквивалентно

void test(int);
person Jim Buck    schedule 19.02.2010

Его можно использовать в следующих случаях (внезапно):

  • общий код:

    boost::function‹int_void› func;

  • другие определения типов:

    typedef int_void* int_void_ptr;

  • декларации:

    недействительным add_callback (обратный вызов int_void *);

Могут быть и другие.

person utnapistim    schedule 19.02.2010

Я думаю, что это законно - следующее демонстрирует его использование:

typedef void f(int);

void t( int a ) {
}

int main() {
    f * p = t;
    p(1); // call t(1)
}

и на самом деле этот код C++ компилируется (с помощью g++) и запускается - хотя я действительно не уверен, насколько это кошерно.

#include <stdio.h>

typedef void f(int);

void t( int a ) {
    printf( "val is %d\n", a );
}

int main() {
    f & p = t;   // note reference not pointer
    p(1);
}
person Community    schedule 19.02.2010
comment
Да, я знаю, что вы можете использовать его как указатель, но я специально спросил, можно ли его использовать без него :P (И, если нет, почему я могу определить переменную такого типа) My question is: can it be used "alone", without a pointer? That is, is it possible to use it as simply int_void and not int_void*? - person Thomas Bonini; 19.02.2010
comment
@ Андреас Андреас Нет. Что бы это значило? - person ; 19.02.2010
comment
Это определенно кошерно. Краткая форма void(&p)() = t; - person Johannes Schaub - litb; 19.02.2010
comment
@Johannes Но как я могу инициализировать ссылку указателем? - person ; 19.02.2010
comment
@ Нил, это не указатель, а функция. Преобразование функции в указатель выполняется только при необходимости, например, с массивами. Как написано, t является lvalue и имеет тип void(int). - person Johannes Schaub - litb; 19.02.2010
comment
@Neil, см. заголовок stackoverflow.com/questions/1516958/ - person Johannes Schaub - litb; 19.02.2010
comment
@Йоханнес Спасибо. Всегда приятно узнавать что-то новое - я не думаю, что когда-либо видел ссылку на функцию раньше, или, может быть, я просто не замечал их. - person ; 19.02.2010
comment
Еще один вопрос по этому поводу: stackoverflow.com/questions/480248/function-references - person Johannes Schaub - litb; 19.02.2010

Указатели на функции являются значениями в C/C++. Функции - нет.

person yfeldblum    schedule 19.02.2010

Это должно работать, приведение не требуется:

void f(int x) { printf("%d\n", x); }

int main(int argc, const char ** argv)
{
    typedef void (*int_void)(int);
    int_void test = f;
    ...
 }

Имя функции «превращается» в указатель на функцию каждый раз, когда вы используете имя функции в чем-то другом, кроме вызова функции. Если is назначается func ptr того же типа, вам не нужно приведение.

Оригинал

typedef int_void(int);

бесполезен сам по себе, без использования указателя на тип. Итак, ответ на ваш вопрос: «Нет, вы не можете использовать этот typedef без указателя».

person Tim Schaeffer    schedule 19.02.2010