69 Stimmen

Hat schon einmal jemand das Präprozessormakro __COUNTER__ verwendet?

El __COUNTER__ Symbol wird bereitgestellt von VC++ und GCC und ergibt bei jeder Verwendung einen zunehmenden nicht-negativen Integralwert.

Ich bin daran interessiert, zu erfahren, ob jemand es jemals benutzt hat, und ob es etwas ist, das es wert wäre, standardisiert zu werden?

5voto

YourZombieMop Punkte 43

Erzeugen von Klassentyp-IDs (C++)

Ich habe die __COUNTER__ um automatisch Typ-IDs für Entities & Colliders in einem objektorientierten Spiel zu generieren.

Dieses Spiel verwendet Polymorphismus, um seine Funktionalität zu erreichen. Um Child-Objekte zu serialisieren, musste ich einen Weg finden, um Entity Child-Typen zu speichern und sie für das Speichern und Laden von Szenen zu serialisieren/deserialisieren. Wenn ich eine Entität aus einer Speicherdatei lese (deserialisiere), musste ich wissen, welche Eigenschaften zu erwarten sind; mit __COUNTER__ Ich habe eine eindeutige und konstante ID für jede Entitätsklasse und kann sie mit dieser ID als den richtigen Entitätstyp laden.

Dieser Ansatz bedeutet, dass ich, um einen neuen Entity-Typ serialisierbar zu machen, nur Folgendes hinzufügen muss typeID = __COUNTER__; innerhalb des Konstruktors, um die Standard-ID zu überschreiben. Im Fall von Sprite:

Sprite(/* TODO: Sprite Arguments */) : Entity(/* TODO: Entity Arguments */) {
    typeID = __COUNTER__;
}

... und fahren Sie damit fort, die Überlastungen des iostream zu skizzieren:

friend std::ostream& operator<<(std::ostream& os, const Sprite& rhs) {
    return os << /* TODO: Outline Output */;
}
friend std::istream& operator>>(std::istream& is, Sprite& rhs) {
    return is >> /* TODO: Outline Input */;
}

Es ist ein sehr leichtgewichtiger Ansatz zur Erzeugung von Typ-IDs für Ihre Klassen und vermeidet einen Haufen komplizierter Logik. Als Präprozessor-Befehl ist es ziemlich einfach, aber es bietet ein nützliches Werkzeug für einige wichtige Anwendungen.

Anmerkung: Wenn Sie den ID-Wert beim Aufruf des Zählers wieder auf 0 setzen wollen, speichern Sie seinen Wert bei der Erzeugung Ihrer ersten ID und subtrahieren Sie alle nachfolgenden IDs von diesem Wert.

Vielen Dank fürs Lesen! -YZM

3voto

StaceyGirl Punkte 7192

Es wird von Boost.Asio verwendet, um stapellose Koroutinen zu implementieren.

Siehe dies Header-Datei y Beispiele .

Die resultierenden Koroutinen sehen wie folgt aus:

struct task : coroutine
{
  ...
  void operator()()
  {
    reenter (this)
    {
      while (... not finished ...)
      {
         ... do something ...
         yield;
         ... do some more ...
         yield;
       }
     }
   }
   ...
};

3voto

cxwangyi Punkte 537

Eine Verwendung ist in TensorFlow's REGISTER_KERNEL_BUILDER Makro . Jede TensorFlow-Op kann einen oder mehrere Kernel als ihre Implementierungen haben. Diese Kernel werden bei einem Registrar registriert. Die Registrierung eines Kernels wird durch die Definition einer globalen Variable durchgeführt -- der Konstruktor der Variable kann die Registrierung durchführen. Hier verwenden die Autoren __COUNTER__ um jeder globalen Variablen einen eindeutigen Namen zu geben.

#define REGISTER_KERNEL_BUILDER(kernel_builder, ...) \
  REGISTER_KERNEL_BUILDER_UNIQ_HELPER(__COUNTER__, kernel_builder, __VA_ARGS__)

#define REGISTER_KERNEL_BUILDER_UNIQ_HELPER(ctr, kernel_builder, ...) \
  REGISTER_KERNEL_BUILDER_UNIQ(ctr, kernel_builder, __VA_ARGS__)

#define REGISTER_KERNEL_BUILDER_UNIQ(ctr, kernel_builder, ...)          \
  static ::tensorflow::kernel_factory::OpKernelRegistrar                \
  registrar__body__##ctr##__object(                                 \
      SHOULD_REGISTER_OP_KERNEL(#__VA_ARGS__)                       \
      ? ::tensorflow::register_kernel::kernel_builder.Build()   \
      : nullptr,                                                \
      #__VA_ARGS__, [](::tensorflow::OpKernelConstruction* context) \
            -> ::tensorflow::OpKernel* {                \
              return new __VA_ARGS__(context);          \
            });

3voto

Leonard Punkte 12742

Wenn ich die Funktionalität richtig verstehe, wünschte ich, ich hätte diese Funktionalität, als ich in Perl arbeitete und eine Ereignisprotokollierungsfunktion in eine bestehende GUI einfügte. Ich wollte sicherstellen, dass die erforderlichen manuellen Tests (seufz) uns eine vollständige Abdeckung bieten, also protokollierte ich jeden Testpunkt in einer Datei, und die Protokollierung einer __counter__ Wert machte es einfach zu erkennen, was in der Berichterstattung fehlte. So wie es war, habe ich das Äquivalent von Hand kodiert.

2voto

JonS Punkte 601

Ich habe es für einen Treiber-Shim-Layer verwendet, bei dem ich sicherstellen musste, dass mindestens ein physischer Treiber aktiviert war.

Zum Beispiel:

#if defined( USE_DRIVER1 )
#include "driver1.h"
int xxx1 = __COUNTER__;
#endif
#if defined( USE_DRIVER2 )
#include "driver2.h"
int xxx2 = __COUNTER__;
#endif
#if __COUNTER__ < 1
#error Must enable at least one driver.
#endif

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X