Nicht-Member anstelle der Member-Funktion aufrufen

8

Ich habe ein sehr einfaches Problem: Irgendwo gibt es eine Funktion

%Vor%

, das zumindest durch argumentabhängige Namenssuche gefunden wird. Jetzt das Problem:

%Vor%

Dies funktioniert nicht, da die Namenssuche nach dem Auffinden der Elementfunktion beendet wird.

Was muss ich in der angegebenen Zeile schreiben, damit not die Member-Funktion versucht wird, aufgerufen zu werden, sondern dass der Compiler alles tut, was die Member-Funktion nicht tun würde existieren?

Beachten Sie, dass die Lösung nicht ist, um ::size zu schreiben, da dies den argumentabhängigen Namen verhindert Nachschlagen und funktioniert nur, wenn ich weiß wo size deklariert ist.

Weitere Komplikationen:

Ich weiß, dass für jeden relevanten Typ T , für den ich die unten stehende Template-Funktion B::doSomething verwende, irgendwo eine Funktion

sein wird %Vor%

, das zumindest durch argumentabhängige Namenssuche gefunden wird. B sieht folgendermaßen aus:

%Vor%

Ich möchte, dass die Nichtmitgliedsfunktion aufgerufen wird (von der ich sicher bin, dass sie existiert, aber ich kann mir nicht sicher sein, wo sie lebt).

    
JohnB 15.11.2012, 22:16
quelle

4 Antworten

7

Dies ist ein bekanntes Problem, und seine Lösung ist ebenso bekannt. Ich bin überrascht, dass es noch nicht erwähnt wurde. Wenn Sie eine Funktion haben, die kein Mitglied ist:

%Vor%

Sie können die Namenssuche so gestalten, dass sie eine Elementfunktion mit einer using -Deklaration vorziehen:

%Vor%

Wenn der Compiler den Aufruf von size(c) sieht, beginnt er im innersten Bereich und sucht nach etwas mit dem Namen size . Ohne die Deklaration using hätte der Compiler die Member-Funktion im Klassenbereich vor dem Nicht-Member im globalen Namespace gefunden, aber die using -Deklaration ändert dies. Der innerste Bereich ist die Funktion selbst und die using-Deklaration wird vor der Elementfunktion gefunden.

Das Schöne daran ist, dass Sie immer noch Argument-abhängige Suche (ADL) bekommen, weil der eigentliche Aufruf von size(c) nicht qualifiziert ist. Dies bedeutet, dass Sie es in einer Vorlage verwenden können:

%Vor%

... und selbst wenn die korrekte Funktion size in einem anderen Namensraum ist, wird sie von ADL gefunden. Die using -Deklaration muss lediglich auf einige size -Funktion verweisen, nicht unbedingt auf die, die Sie tatsächlich möchten. Es wäre normal, irgendwo eine Standardimplementierung zu haben, die vielleicht das Mitglied aufruft. Die nächste Version des C ++ - Standards (C ++ 17) hat fast sicher eine std::size -Funktion, die genau das tut. Sobald dies weit verbreitet ist, können Sie

schreiben %Vor%

Im Moment können Sie entweder Ihre eigene Standardimplementierung bereitstellen, wie zum Beispiel:

%Vor%

... oder Sie können weiterhin auf die Version für C verweisen und darauf vertrauen, dass ADL die richtige findet.

    
Richard Smith 19.08.2015, 09:15
quelle
6

Wenn Sie Ihre eigene Mitgliedsfunktion nicht umbenennen können, können Sie einen schmutzigen Trick anwenden:

%Vor%     
Kerrek SB 15.11.2012 22:19
quelle
3

Der Vollständigkeit halber und zu der akzeptierten Antwort von Richard Smith hinzugefügt:

Meine Lösung sieht jetzt wie folgt aus:

%Vor%

Auf diese Weise muss ich keine Header einfügen, die nicht wirklich benötigt werden.

    
JohnB 20.08.2015 19:50
quelle
0

Sie können SFINAE verwenden, um zu erkennen, ob Sie eine Mitgliedsfunktion haben oder nicht.

Ich habe diese Antwort verwendet, um solche Templatests auf die Größe vorzubereiten:

%Vor%

Nun, der Hauptteil, 2 Funktionen - aufgrund von SFINAE wird nur eine davon ausgewählt:

%Vor%

Nun, auf auto-magische Weise - abhängig davon, ob Sie B :: size (C) haben oder nicht - wird die globale oder lokale Funktion aufgerufen:

%Vor%

Es gibt Global size aus. Um Local size zu erhalten - aktiviere einfach die lokale B::size(C) -Funktion. Dies kann nicht mit einer anderen Antwort erreicht werden ,,,,

Arbeitsbeispiel hier bei ideone

    
PiotrNycz 15.11.2012 23:43
quelle

Tags und Links