Альтернатива получению адреса стандартной библиотечной функции / возможно плохо сформированного поведения - PullRequest
2 голосов
/ 04 июля 2019

проблема: возможно некорректное поведение, взяв адрес стандартной библиотечной функции ... см. Пример ниже.поэтому я ищу альтернативу взятию адреса стандартной библиотечной функции.

в соответствии с http://eel.is/c++draft/namespace.std#6 и, как отмечено @Caleth в Почему назначение функции-указателя работает в прямом назначениино не в условном операторе

"Обратите внимание, что вы полагаетесь на неопределенное (возможно, плохо сформированное) поведение, беря адрес стандартной библиотечной функции (которая не обозначена как адресуемая)"

Как в этом примере:

int (*fun)(int) = std::toupper;
int t = fun('x');

мои вопросы:

1) нет ли безопасного способа вызова (в этом примере) toupper по указателю?

2) делает static_cast безопасный указатель на функцию библиотеки std?например:

int (*fun)(int) = static_cast<int(*)(int)>(std::toupper);
int t = fun('x');

2) Есть ли другой способ достижения перечисленных ниже функций с помощью одной функции с подписью «int fun (int)»

bool choice = true;
int (*fun)(int);

if (choice) {
    fun = std::toupper;
}
else {
    fun = std::tolower;
}

int t = fun('x');

1 Ответ

4 голосов
/ 04 июля 2019

нет ли безопасного способа вызова (в этом примере) toupper по указателю?

Не напрямую, только через один уровень косвенности (см. Ниже).

делает static_cast безопасным ли указатель на функцию библиотеки std?

Нет. Это может привести к перегрузке, установленной для одной конкретной сигнатуры функции, но это не имеет никакого отношения к тому, разрешено ли вам брать адрес этой функции.

Есть ли еще один способ для достижения перечисленных ниже функций с помощью одной функции с подписью int fun(int)

Есть альтернатива, вы можете заключить вызов функции в две лямбды. Это требует небольшого изменения исходного фрагмента:

bool choice = true;
int (*fun)(int);

if (choice)
    fun = [](int ch){ return std::toupper(ch); };
else
    fun = [](int ch){ return std::tolower(ch); };

int t = fun('x');

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

...