Как работает сложное выражение для приведения типов в стиле C? - PullRequest
3 голосов
/ 29 ноября 2011

Я искал способ прописать стандартную строку в верхнем регистре.Ответ, который я нашел, включал следующий код:

int main()
{
    // explicit cast needed to resolve ambiguity
    std::transform(myString.begin(), myString.end(), myString.begin(),
      (int(*)(int)) std::toupper)
}

Может ли кто-нибудь объяснить выражение «(int (*) (int))»?Все остальные примеры и описания приведения, которые я нашел, используют только простые выражения приведения типов.

Ответы [ 4 ]

5 голосов
/ 29 ноября 2011

На самом деле это просто приведение типов - но к типу указателя на функцию.

std::toupper выпускается в двух вариантах.Один берет int и возвращает int;другой принимает int и const locale& и возвращает int.В данном случае это первый запрос, но компилятор, как правило, не знает, как это сделать.

(int(*)(int)) - приведение к указателю на функцию, которое принимает int (правая рукачасть) и возвращает int (левая часть).Только первая версия toupper может быть приведена таким образом, поэтому она не имеет значения для компилятора.

3 голосов
/ 29 ноября 2011

(int (*) (int)) - это имя указателя функции type .Функция возвращает (int) , является функцией * и принимает аргумент (int) .

2 голосов
/ 29 ноября 2011

Как уже упоминалось, int (*)(int) - это указатель типа на функцию, которая принимает и возвращает int.Однако здесь отсутствует то, что делает это приведенное выражение: в отличие от других приведенных выражений, оно не действительно приводит (то есть не преобразует значение в другой тип), но выбирает из перегруженного набора функций с именем std::toupper тот, который имеет сигнатуру int(int).

Обратите внимание, однако, что этот метод несколько хрупкий: если по какой-то причине нет соответствующей функции (например, потому чтосоответствующий заголовок не был включен), но только одна несовпадающая функция (поэтому не возникает двусмысленности), тогда это выражение приведения действительно превратится в приведение, точнее reinterpret_cast, с нежелательными эффектами.Чтобы убедиться, что не произошло непреднамеренного приведения, вместо синтаксиса приведения в стиле C следует использовать синтаксис приведения в стиле C ++: static_cast<int(*)(int)>(std::toupper) (на самом деле, в случае std::toupper этот случай не может произойти, потому что единственная альтернативная функция является шаблонной ипоэтому неоднозначно, однако это может произойти с другими перегруженными функциями).

По совпадению, синтаксис приведения нового стиля также более читабелен в этом случае.

Еще одна возможность, которая работает без приведенияВыражение выглядит следующим образом:

int (*ptoupper)(int) = &std::toupper; // here the context provides the required type information
std::transform(myString.begin(), myString.end(), myString.begin(), ptoupper);

Обратите внимание, что причина, по которой контекст не может предоставить необходимую информацию, заключается в том, что std::transform шаблонируется в последнем аргументе, поэтому компилятор не может определить правильную функцию для выбора.

2 голосов
/ 29 ноября 2011
int function(int);

Функция, принимающая int и возвращающая int.

int (*function_pointer)(int);

Указатель на функцию, принимающую int и возвращающую int.

int (*)(int)

Тип указателя на функцию, принимающую int и возвращающую int.

std::toupper из <cctype>, уже имеет тип int (*)(int), но в <locale> шаблонизируется charT, что, как я полагаю, и есть повод для актерского состава.Но ptr_fun будет понятнее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...