Передать функцию по значению (?) вместо указателя на функцию?

Извините, если это было задано раньше, но я не смог его найти.

Итак, я пытаюсь рассказать о шаблонах и новых возможностях С++ 11 (в основном лямбда, что мне всегда нравилось на других языках).

Но в моих тестах я пришел к чему-то, что я понятия не имел, что это сработало, и я пытаюсь понять, как это работает, но не могу понять это.

Следующий код:

template <class Func>
void Test( Func callback ) {
    callback( 3 );
}

void Callback( int i ) {
    std::cout << i << std::endl;
}

int main( int argc, char** argv ) {
    Test( &Callback ); // this I was expecting to work, compiler will see its a pointer to a function
    Test( Callback ); // this also works, but how?!
    return 0;
}

Если я понимаю, как работают шаблоны, в основном они представляют собой схему для компилятора, чтобы знать, что строить, поэтому первый вызов Test( &Callback ); я ожидал работать, потому что компилятор увидит, что шаблон получает адрес функции и будет предположим, что аргументы должны быть указателями.

Но каков второй звонок? Что такое шаблон, предполагающий это? Копия функции (если это даже имеет смысл)?

8
18 авг. '11 в 20:02
источник поделиться
4 ответов

Функция неявно конвертируется в указатель на себя; это преобразование происходит практически везде. Test(Callback) точно совпадает с Test(&Callback). Нет никакой разницы. В обоих случаях Func выводится как void(*)(int).

Указатели функций странные. Вы можете узнать больше о них в "Почему все эти сумасшедшие определения указателей функций все работают?"

14
18 авг. '11 в 20:03
источник

В С++ функции не являются первоклассными объектами, что означает, что "функция как значение" не имеет смысла. Вот почему имя функции всегда было неявно конвертируемой в указатель на нее.

3
18 авг. '11 в 20:08
источник

Функции неявно конвертируются в указатели на функции. Если нет, то невозможно получить значение функции или ссылку. Хотя странно вы можете создать тип значения функции, вы просто ничего не можете ему присваивать.

Вот фрагмент кода, который демонстрирует, как lambdas и различные обратные вызовы реагируют на шаблоны.

2
18 авг. '11 в 20:21
источник

В С++ 11 (и boost и tr1) у нас есть std:: function как тип шаблона для хранения функторов, lambdas и функций. Таким образом, вы можете определенно иметь концепцию сохранения значения функции в переменной типа std:: function. эта переменная также может быть "пустой", что означает, что в ней не сохраняется функция (ссылка). Тогда его нельзя вызвать.

Оригинальный вопрос относится к тому, что в отличие от C, С++ допускает ссылки на функции. Кроме того, по причинам совместимости с C имя функции может выродиться до указателя функции. Но из-за перегрузки вещи более "интересны" на С++, чем в C.

0
20 окт. '11 в 11:47
источник

Посмотрите другие вопросы по меткам или Задайте вопрос