Потому, что неправильно объявлен первый формальный параметр функции bar. Правильно так
void bar(double f(double), double p1);
После этого исправления программа компилируется и выполняется успешно: http://ideone.com/Y6Rcx.
FS>Как такое возможно(особенно запись double(double)) и как такое соотносится с компиляторами и стандартом?
Нормальная запись, которая обозначает тип функции с одним параметром типа double и типом возвраемого значения double. Запись double(double) — это "голый" тип, без идентификатора. Добавлять идентификатор, если он понадобится, в этом случае нужно не в конец записи, а перед скобкой: double foo(double);
Только нужно учитывать, что параметры-функции по стандарту автоматически трактуются компилятором как указатели на функции. Следующие объявления эквивалентны:
Здравствуйте, rg45, Вы писали:
r> FS>Как такое возможно(особенно запись double(double)) и как такое соотносится с компиляторами и стандартом?
r> Нормальная запись, которая обозначает тип функции с одним параметром типа double и типом возвраемого значения double. Запись double(double) — это "голый" тип, без идентификатора. Добавлять идентификатор, если он понадобится, в этом случае нужно не в конец записи, а перед скобкой: double foo(double);
Впервые слышу про термин "голый тип", но понятно — что это сигнатура метода и она как-то трактуется компилятором при шаблонной подстановке как указатель на функцию. К сожалению я не знаю с++ template-preprocessors, а было бы интересно посмотреть какой в итоге код получается при подстановке типа double(double) в метод. Все-таки по-видимому подобные шаблонные параметры реализованы на уровне компилятора, а не на уровне С++.
Осталось только понять, как согласуется со всем сказанным стандарт.
Здравствуйте, Fedor Sumkin, Вы писали: FS>Здравствуйте, rg45, Вы писали: r>> FS>Как такое возможно(особенно запись double(double)) и как такое соотносится с компиляторами и стандартом? r>> Нормальная запись, которая обозначает тип функции с одним параметром типа double и типом возвраемого значения double. Запись double(double) — это "голый" тип, без идентификатора. Добавлять идентификатор, если он понадобится, в этом случае нужно не в конец записи, а перед скобкой: double foo(double); FS>Впервые слышу про термин "голый тип", но понятно — что это сигнатура метода и она как-то трактуется компилятором при шаблонной подстановке как указатель на функцию. К сожалению я не знаю с++ template-preprocessors, а было бы интересно посмотреть какой в итоге код получается при подстановке типа double(double) в метод. Все-таки по-видимому подобные шаблонные параметры реализованы на уровне компилятора, а не на уровне С++. FS>Осталось только понять, как согласуется со всем сказанным стандарт.
"Голый тип" — это не термин — просто попытка объяснить "на пальцах" тот факт, что иногда в деклараторах идентификатор может отсутствовать.
И когда ты пишешь:
foo<double(double)>();
код в итоге получается такой же, как если бы ты написал:
typedef double Bar(double);
foo<Bar>();
И использование такой записи вовсе не обязательно сопряжено с шаблонами, например:
typeid(double(double)); //Получение информации о типеvoid foo(double(double)); //Предварительное объявление функции, принимающей указатель на функцию
С таким же успехом мы могли бы написать:
typeid(int); //Получение информации о типеvoid foo(int); //Предварительное объявление функции
double(double) — это обычный декларатор только без идентификатора, понимаешь?
И никакие это не особенности компиляторов — это описано в действующем стандарте языка:
8.1 Type names
1 To specify type conversions explicitly, and as an argument of sizeof, new, or typeid, the name of a
type shall be specified. This can be done with a type-id, which is syntactically a declaration for an object or
function of that type that omits the name of the object or function.
It is possible to identify uniquely the location in the abstract-declarator where the identifier would appear
if the construction were a declarator in a declaration. The named type is then the same as the type of the
hypothetical identifier. [Example:
int// int iint * // int *piint *[3] // int *p[3]int (*)[3] // int (*p3i)[3]int *() // int *f()int (*)(double) // int (*pf)(double)
name respectively the types “int,” “pointer to int,” “array of 3 pointers to int,” “pointer to array of 3
int,” “function of (no parameters) returning pointer to int,” and “pointer to a function of (double)
returning int.’’ ]
2 A type can also be named (often more easily) by using a typedef (7.1.3).
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали: R>Здравствуйте, Fedor Sumkin, Вы писали: FS>>Здравствуйте, rg45, Вы писали:
r>>> FS>Как такое возможно(особенно запись double(double)) и как такое соотносится с компиляторами и стандартом? FS>>Осталось только понять, как согласуется со всем сказанным стандарт. R>"Голый тип" — это не термин — просто попытка объяснить "на пальцах" тот факт, что иногда в деклараторах идентификатор может отсутствовать.
Лично меня здесь смущает отсутствие '*', а не идентификатора.