шаблонный параметр в std::function
От: Fedor Sumkin
Дата: 29.05.11 22:06
Оценка:
Почему сейчас код работает(gcc 4.5.1), а если раскомментировать доп. блоки не будет работать?
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <map>
#include <math.h>
 
using namespace std;
 
template<class T, class U>
void foo(T f, U p1)
{
    cout << f(p1);
}
 
/*void bar(double(double) f, double p1)
{
    cout << f(p1);
}*/
 
int main ()
{
    foo<double(double), double>(cos, 3.1415);
/*    bar(cos, 3.1415);*/
}

https://ideone.com/IZ6bB

Как такое возможно(особенно запись double(double)) и как такое соотносится с компиляторами и стандартом?
avalon 1.0rc3 rev 419, zlib 1.2.5
Re: шаблонный параметр в std::function
От: rg45 СССР  
Дата: 30.05.11 07:23
Оценка: 4 (3) +1
Здравствуйте, Fedor Sumkin, Вы писали:

FS>Почему сейчас код работает(gcc 4.5.1), а если раскомментировать доп. блоки не будет работать?

FS>
FS>//...
FS>void bar(double(double) f, double p1)
FS>//...
FS>


Потому, что неправильно объявлен первый формальный параметр функции bar. Правильно так
void bar(double f(double), double p1);


После этого исправления программа компилируется и выполняется успешно: http://ideone.com/Y6Rcx.

FS>Как такое возможно(особенно запись double(double)) и как такое соотносится с компиляторами и стандартом?


Нормальная запись, которая обозначает тип функции с одним параметром типа double и типом возвраемого значения double. Запись double(double) — это "голый" тип, без идентификатора. Добавлять идентификатор, если он понадобится, в этом случае нужно не в конец записи, а перед скобкой: double foo(double);

Только нужно учитывать, что параметры-функции по стандарту автоматически трактуются компилятором как указатели на функции. Следующие объявления эквивалентны:
void bar(double f(double), double p1);
void bar(double (*f)(double), double p1);
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: шаблонный параметр в std::function
От: Fedor Sumkin
Дата: 30.05.11 20:21
Оценка:
Здравствуйте, rg45, Вы писали:

r> FS>Как такое возможно(особенно запись double(double)) и как такое соотносится с компиляторами и стандартом?


r> Нормальная запись, которая обозначает тип функции с одним параметром типа double и типом возвраемого значения double. Запись double(double) — это "голый" тип, без идентификатора. Добавлять идентификатор, если он понадобится, в этом случае нужно не в конец записи, а перед скобкой: double foo(double);


Впервые слышу про термин "голый тип", но понятно — что это сигнатура метода и она как-то трактуется компилятором при шаблонной подстановке как указатель на функцию. К сожалению я не знаю с++ template-preprocessors, а было бы интересно посмотреть какой в итоге код получается при подстановке типа double(double) в метод. Все-таки по-видимому подобные шаблонные параметры реализованы на уровне компилятора, а не на уровне С++.

Осталось только понять, как согласуется со всем сказанным стандарт.
avalon 1.0rc3 rev 419, zlib 1.2.5
Re[3]: шаблонный параметр в std::function
От: rg45 СССР  
Дата: 31.05.11 11:54
Оценка:
Здравствуйте, 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.


    type-id:
        type-specifier-seq abstract-declarator(opt)
    type-specifier-seq:
        type-specifier type-specifier-seq(opt)
        abstract-declarator:
    ptr-operator abstract-declarator(opt)
        direct-abstract-declarator
    direct-abstract-declarator:
        direct-abstract-declarator(opt)
        ( parameter-declaration-clause ) cv-qualifier-seq(opt) exception-specification(opt)
        direct-abstract-declarator(opt) [ constant-expression(opt) ]
        ( abstract-declarator )


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 i
int *           // int *pi
int *[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).
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: шаблонный параметр в std::function
От: B0FEE664  
Дата: 31.05.11 12:05
Оценка:
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Fedor Sumkin, Вы писали:
FS>>Здравствуйте, rg45, Вы писали:

r>>> FS>Как такое возможно(особенно запись double(double)) и как такое соотносится с компиляторами и стандартом?

FS>>Осталось только понять, как согласуется со всем сказанным стандарт.
R>"Голый тип" — это не термин — просто попытка объяснить "на пальцах" тот факт, что иногда в деклараторах идентификатор может отсутствовать.

Лично меня здесь смущает отсутствие '*', а не идентификатора.
И каждый день — без права на ошибку...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.