web-dev-qa-db-fra.com

C ++ 11: comment alias une fonction?

Si j'ai une classe Foo dans la barre d'espace de noms:

namespace bar
{
    class Foo { ... }
};

Je peux alors:

using Baz = bar::Foo;

et maintenant c'est comme si j'avais défini la classe dans mon espace de noms avec le nom Baz.

Est-il possible de faire de même pour les fonctions?

namespace bar
{
    void f();
}

Et alors:

using g = bar::f; // error: ‘f’ in namespace ‘bar’ does not name a type

Quelle est la façon la plus propre de procéder?

La solution doit également tenir pour les fonctions de modèle.

Définition: Si une entité B est un alias de A, alors si certains ou tous les usages (pas les déclarations ou définitions bien sûr) de A sont remplacés par B dans le code source que le code généré (supprimé) reste le même. Par exemple typedef A B est un alias. #define B A est un alias (au moins). T& B = A n'est pas un alias, B peut effectivement être implémenté comme un pointeur indirect, alors qu'un A "sans alias" peut utiliser la "sémantique immédiate".

61
Andrew Tomazos

Vous pouvez définir un alias de fonction (avec un peu de travail) en utilisant un transfert parfait:

template <typename... Args>
auto g(Args&&... args) -> decltype(f(std::forward<Args>(args)...)) {
  return f(std::forward<Args>(args)...);
}

Cette solution s'applique même si f est surchargé et/ou un modèle de fonction.

63
Jeremiah Willcock

Les classes sont types, elles peuvent donc être aliasées avec typedef et using (en C++ 11).

Les fonctions ressemblent beaucoup plus à objets, il n'y a donc pas de mécanisme pour les alias. Au mieux, vous pouvez utiliser des pointeurs de fonction ou des références de fonction:

void (*g)() = &bar::f;
void (&h)() = bar::f;

g();
h();

Dans la même veine, il n'y a pas de mécanisme d'alias variables (à court de pointeurs ou de références).

20
Kerrek SB

Absolument:

#include <iostream>

namespace Bar
{
   void test()
   {
      std::cout << "Test\n";
   }


   template<typename T>
   void test2(T const& a)
   {
      std::cout << "Test: " << a << std::endl;
   }
}

void (&alias)()        = Bar::test;
void (&a2)(int const&) = Bar::test2<int>;

int main()
{
    Bar::test();
    alias();
    a2(3);
}

Essayer:

> g++ a.cpp
> ./a.out
Test
Test
Test: 3
>

Une référence est un alias vers un objet existant.
Je viens de créer une référence à une fonction. La référence peut être utilisée exactement de la même manière que l'objet d'origine.

15
Martin York

Le pointeur de fonction constexpr peut être utilisé comme alias de fonction.

namespace bar
{
    int f();
}

constexpr auto g = bar::f;

À l'endroit où l'alias est utilisé, le compilateur appellera la fonction alias même lors de la compilation sans optimisation.

Avec GCC7, l'utilisation suivante

int main()
{
    return g();
}

devient

main:
  Push rbp
  mov rbp, rsp
  call bar::f()  # bar::f() called directly.
  pop rbp
  ret

L'assembly a été généré dans Explorateur du compilateur .

14
Paweł Bylica

Il est possible d'introduire la fonction dans une portée différente sans changer son nom. Vous pouvez donc alias une fonction avec un nom qualifié différent:

namespace bar {
  void f();
}

namespace baz {
  using bar::f;
}

void foo() {
  baz::f();
}
10
Jason Haslam

Ce n'est pas du C++ standard, mais la plupart des compilateurs fournissent un moyen de le faire. Avec GCC, vous pouvez faire ceci:

void f () __attribute__ ((weak, alias ("__f")));

Cela crée le symbole f comme alias pour __f. Avec VC++, vous faites la même chose de cette façon:

#pragma comment(linker, "/export:f=__f")
7
Tom

Vous pouvez utiliser de bonnes vieilles macros

namespace bar
{
    void f();
}

#define f bar::f

int main()
{
    f();
}
1
Romeno