web-dev-qa-db-fra.com

Comment attribuer un alias à un nom de fonction en C++?

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:

  1. #define holler printf
  2. void (*p)() = fn; //function pointer
  3. void (&r)() = fn; //function reference
  4. inline void g(){ f(); }
88
Agnel Kurian

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);
    
97
sasha.sochka

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
32
Brian R. Bondy
typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;

Ça devrait vous aller.

21
jer

int (*holler)(const char*, ...) = std::printf;

10
MSalters

Utilisez un wrapper en ligne. Vous obtenez les deux API, mais conservez la mise en œuvre unique.

7
John

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)...); \
}
2
sailfish009

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é.

0
Kevin Anderson