Il est facile de créer un nouveau nom pour un type, une variable ou un espace de noms. Mais comment attribuer un nouveau nom à une fonction? Par exemple, je souhaite utiliser le nom holler
pour printf
. #define est évident ... de toute autre manière?
Solutions:
#define holler printf
void (*p)() = fn; //function pointer
void (&r)() = fn; //function reference
inline void g(){ f(); }
Il y a différentes approches:
Avec C++ 11 avec des fonctions non surchargées sans modèle, vous pouvez simplement utiliser:
const auto& new_fn_name = old_fn_name;
Si cette fonction comporte plusieurs surcharges, vous devez utiliser static_cast
:
const auto& new_fn_name = static_cast<OVERLOADED_FN_TYPE>(old_fn_name);
Exemple: il y a deux surcharges de la fonction std::stoi
int stoi (const string&, size_t*, int);
int stoi (const wstring&, size_t*, int);
Si vous souhaitez créer un alias pour la première version, utilisez les éléments suivants:
const auto& new_fn_name = static_cast<int(*)(const string&, size_t*, int)>(std::stoi);
Remarque: il n'y a aucun moyen de créer un alias pour surcharger la fonction, de sorte que toutes ses versions surchargées fonctionnent. Vous devez donc toujours spécifier la surcharge exacte de la fonction souhaitée.
Avec C++ 14, vous pouvez aller encore plus loin avec les variables de modèle constexpr
. Cela vous permet d’aliaser des fonctions basées sur un modèle:
template<typename T>
constexpr void old_function(/* args */);
template<typename T>
constexpr auto alias_to_old = old_function<T>;
De plus, à partir de C++ 11, vous avez une fonction appelée std::mem_fn
qui permet d’aliaser les fonctions membres. Voir l'exemple suivant:
struct A {
void f(int i) {
std::cout << "Argument: " << i << '\n';
}
};
A a;
auto greet = std::mem_fn(&A::f); // alias to member function
// prints "Argument: 5"
greet(a, 5); // you should provide an object each time you use this alias
// if you want to bind an object permanently use `std::bind`
greet_a = std::bind(greet, a, std::placeholders::_1);
greet_a(3); // equivalent to greet(a, 3) => a.f(3);
Vous pouvez créer un pointeur de fonction ou une référence de fonction:
void fn()
{
}
//...
void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference
typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;
Ça devrait vous aller.
int (*holler)(const char*, ...) = std::printf;
Utilisez un wrapper en ligne. Vous obtenez les deux API, mais conservez la mise en œuvre unique.
De fluentcpp : ALIAS_TEMPLATE_FUNCTION (f, g)
#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF) \
template<typename... Args> \
inline auto highLevelF(Args&&... args) -> decltype(lowLevelF(std::forward<Args>(args)...)) \
{ \
return lowLevelF(std::forward<Args>(args)...); \
}
Il est à noter ici, IMO, que si la question initiale (et les bonnes réponses) sont certainement utiles si vous souhaitez renommer une fonction (il existe de bonnes raisons de le faire!), Si vous ne voulez que supprimer un espace de noms profond, mais conservez le nom, il y a le mot clé using
pour ceci:
namespace deep {
namespace naming {
namespace convention {
void myFunction(int a, char b) {}
}
}
}
int main(void){
// A pain to write it all out every time
deep::naming::convention::myFunction(5, 'c');
// Using keyword can be done this way
using deep::naming::convention::myFunction;
myFunction(5, 'c'); // Same as above
}
Cela présente également l'avantage d'être limité à une portée, même si vous pouvez toujours l'utiliser au niveau supérieur d'un fichier. J'utilise souvent ceci pour cout
et endl
donc je n'ai pas besoin de mettre TOUT de std
avec le using namespace std;
classique en haut d'un fichier, mais c'est également utile si vous utilisez quelque chose comme std::this_thread::sleep_for()
beaucoup dans un seul fichier ou fonction mais pas partout, et pas d'autres fonctions de l'espace de noms. Comme toujours, il est déconseillé de l'utiliser dans des fichiers .h, sinon vous pollueriez l'espace de noms global.
Ce n'est pas la même chose que le "renommage" ci-dessus, mais c'est souvent ce qui est vraiment souhaité.