Насколько я знаю для функций в с++
(в силу исторических причин) верно следующее тождество:
foo == &foo;
Тобишь указатель на функцию это тоже что и функция и наоборот. Однако, типы у этих значений разные:
std::is_same<decltype(foo), decltype(&foo)>::value == false;
Почему типы разные? И какие они?
Типы у функции и указателя на функцию действительно совершенно разные. Однако поведение значений типа "функция" в выражениях в С и С++ во многом аналогично поведению значений типа "массив": во многих контекстах в выражениях значение типа "функция" само по себе, безо всякого участия с вашей стороны неявно преобразуется ("decays") к значению типа "указатель на функцию".
Ваш пример с оператором ==
- как раз пример такого контекста. Формально слева у вас стоит функция, а справа - указатель на функцию, который вы получили при помощи оператора &
. Но фактически до оператора ==
левый операнд "доходит" уже преобразованным к типу "указатель на функцию". Этот указатель "получился сам", как результат вышеупомянутого неявного преобразования.
Соверешенно аналогичным образом для массива int a[10]
выполняется равенство
&a[0] == a
несмотря на то, что исходные типы в левой и правой части этого равенства совершенно разные.
Для случая функции будут выполняться также и равенства
*foo == &foo
***foo == ***&***&**foo;
и т.п.
В таких контекстах, как унарный оператор &
, оператор sizeof
, спецификатор decltype
и др., неявного преобразования не происходит. Поэтому в этих контекстах вы видите истинный, непреобразованный тип функции. (То же самое справедливо и для массивов).
Вышесказанное относится к поведению значений типа "функция" в выражениях. Поведение самого типа "функция" в объявлениях - совсем другая, отдельная история. В объявлениях тип "функция" почти всегда остается типом "функция".
Например, объявление
decltype(foo) a = foo;
является некорректным. decltype(foo)
видит тип "функция", в результате чего идентификатор a
объявляется с типом "функция". Функцию невозможно "инициализировать".
В то же время, согласно правилам поведения decltype
, вот такое объявление
decltype((foo)) b = foo;
является совершенно корректным - оно объявляет b
как переменную-указатель на функцию. Благодаря "лишним" скобкам внутри decltype
, значение типа "функция" успевает неявно преобразоваться к значению типа "указатель" и decltype
видит уже не тип "функция", а тип "указатель на функцию".
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Помогите разобраться, стоит задача: нужно по таймеру вызывать функцию в другом потоке Вот что у меня получается