Was macht ## (Doppel-Hash) in einer Präprozessor-Direktive?

89
#define DEFINE_STAT(Stat) \
struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;

Die obige Zeile stammt aus Unreal 4, und ich weiß, dass ich sie in den unwirklichen Foren nachfragen könnte, aber ich denke, dies ist eine allgemeine C ++ - Frage, die hier gestellt werden muss.

Ich verstehe, dass die erste Zeile ein Makro definiert, aber ich bin nicht gut mit Präprozessor-Spielereien in C ++ vertraut und deshalb bin ich dort verloren. Die Logik sagt mir, dass der Backslash bedeutet, dass die Deklaration in der nächsten Zeile fortgesetzt wird.

FThreadSafeStaticStat sieht ein bisschen wie eine Vorlage aus, aber da ist # los und eine Syntax, die ich noch nie in C ++ gesehen habe

Könnte mir jemand sagen, was das bedeutet? Ich verstehe, dass Sie möglicherweise keinen Zugriff auf Unreal 4 haben, aber es ist nur die Syntax, die ich nicht verstehe.

DavidColson
quelle
5
Sie können über ## Operator auf cppreference unter anderem lesen
Cubbi
1
##ist / könnte der Verkettungsoperator genannt werden.
Dyp
1
Oh, das ist ziemlich cool! Es erklärt ziemlich viel, danke. Aber warum wird das Schlüsselwort struct verwendet? Die Zeile sieht eher aus wie eine Variablendefinition
DavidColson
1
Das structführt, soweit ich das beurteilen kann, einen ausgeklügelten Typspezifizierer ein .
Dyp
2
Der offizielle Name lautet "Token Pasting Operator", da zwei Vorverarbeitungstoken kombiniert werden, um einen weiteren zu erstellen. Beachten Sie, dass es nur dann gültig ist , wenn das Ergebnis eine gültige Vorverarbeitung Token ist, zB kann man nicht tun + ## 3zu machen +3. (Aber Sie können + 3natürlich ohne den Betreiber tun )
MM

Antworten:

168

## ist der Präprozessoroperator für die Verkettung.

Also, wenn Sie verwenden

DEFINE_STAT(foo)

irgendwo im Code wird es durch ersetzt

struct FThreadSafeStaticStat<FStat_foo> StatPtr_foo;

bevor Ihr Code kompiliert wird.

Hier ist ein weiteres Beispiel aus einem Blog-Beitrag von mir, um dies weiter zu erklären.

#include <stdio.h>

#define decode(s,t,u,m,p,e,d) m ## s ## u ## t
#define begin decode(a,n,i,m,a,t,e)

int begin()
{
    printf("Stumped?\n");
}

Dieses Programm würde erfolgreich kompilieren und ausführen und die folgende Ausgabe erzeugen:

Stumped?

Wenn der Präprozessor für diesen Code aufgerufen wird,

  • begin wird ersetzt durch decode(a,n,i,m,a,t,e)
  • decode(a,n,i,m,a,t,e) wird ersetzt durch m ## a ## i ## n
  • m ## a ## i ## n wird ersetzt durch main

Somit wird effektiv begin()durch ersetzt main().

Susam Pal
quelle
8
Ich hatte nicht erwartet, so viel darüber nachzudenken, um das Verhalten von ## zu lernen, aber ich denke, jetzt werde ich es nie vergessen? So danke.
NicoBerrogorry
2
Ich brauchte eine Sekunde, um ihm zu folgen, aber das war eine fantastische Antwort auf die Frage. Vielen Dank.
n00dle