C++ Bedingte Kompilierung: #ifdef/#endif in .h aber #define ausserhalb?

T_55

Lieutenant
Registriert
Feb. 2013
Beiträge
643
Hallo,

bedingte Kompilierung ist richtig praktisch aber jetzt hab ich ein Problem, denn ich will die einzugrenzenden Quelltexte (#ifdef #endif) in einer header-file haben aber die symbolische Konstanten (#define) sollen in unterschiedlichen cpp landen welche die header-file included. Hintergrund, ich hab 2 Projekte welche die gleiche .h nutzen. Die .h hat aktuell für jedes Projekt eine symbolische Konstante und ermöglicht so ein paar individuelle Abweichungen.
Nachteil: wenn ich von Projekt zu Projekt springe muss ich immer jeweils die andere symbolische Konstante auskommentieren (//) und die eigene wieder frei machen.
Ziel: Jetzt hätte ich die symbolische Konstante aber gerne am liebsten in der cpp der verschiedenen Projekte (welche die geteilte .h einbinden), denn dann würde alles automatisch funktionieren weil jedes Projekt einfach nur seine individuelle symbolische Konstante hat und so entsprechend seinen Code in der .h freischaltet. Geht aber nicht.
Ich hab das #define natürlich vor das #include der h-file platziert aber das funktioniert leider nicht. Es funktioniert aktuell leider nur wenn symbolische Konstante und #ifdef #endif in einer file sind.

Frage: Geht es irgendwie trotzdem?

Gruß
 
T_55 schrieb:
Dann machst du was falsch. Dieser code funktioniert:

test.h
C++:
#pragma once

#include <cstdint>

#ifdef TEST_DEFINE
uint32_t testint = 34;
#else
uint32_t testint = 35;
#endif // TEST_DEFINE

test.cpp
C++:
#define TEST_DEFINE

#include <iostream>
#include "test.h"

int main()
{
    std::cout << testint; // 34
}


Edit: Falls du das in beiden Projekten definierst, nur mit anderen Werten, dann musst du #if verwenden, z.B:
C++:
#if TEST_DEFINE == 1
uint32_t testint = 34;
#else
uint32_t testint = 35;
#endif // TEST_DEFINE
 
  • Gefällt mir
Reaktionen: T_55 und new Account()
Hallo

Soweit ich das verstanden habe musst du das aus dem cpp rausnehmen und stattdessen beim Compile-Schritt direkt dem Compiler übergeben. Dann kannst du das für jedes Projekt getrennt einschalten.

Grüße,
Znep
 
Dein Problem liegt vermutlich daran, weil du für die Header-Datei eine eigene Translation kompiliert wird - separat. Damit kannst du als define angeben was du willst, er wird immer dass aus der Translation Unit verwenden - sprich der Standard der gesetzt ist.

Mir fällt hier eine tolle Lösung ein:

Mach aus der Header-Datei eine Single-Header-File und pack den Implementierungsblock direkt ans Ende der Header-Datei, aber schütze diesen Block mit nem eigenen aktivierungsdefine ->

Code:
// ----------------------------------------------------
// Implementation
// ----------------------------------------------------

#if !defined(XXX_IMPLEMENTED) && defined(XXX_IMPLEMENTATION)
#define XXX_IMPLEMENTED 1

// der source von der .cpp datei

#endif // !XXX_IMPLEMENTED && XXX_IMPLEMENTATION

In deiner Main-Translation-Unit, includierst du dann die header file und davor setzt du alles Defines die du brauchst, z.b. #define XXX_MY_CONSTANT 42.
Wichtig aber ist hier, dass du kurz bevor du die header Datei einbindest ein define XXX_IMPLEMENTATION erstellst. Damit ist dann auch der Source in deiner Main Translation Unit drinne.

Damit kannst du dann die Defines viel flexibler steuern und kannst dich darauf verlassen dass deine defines auch ankommen. Auch kannst du auch viel feiner steuern, ob Funktionen static oder extern oder dll export/import sind.

Hier eine Beispielbibliothek die genau so auf aufgebaut ist:
https://github.com/f1nalspace/final_game_tech/blob/master/final_memory.h
 
  • Gefällt mir
Reaktionen: T_55
@coolmodi interessant, genau das geht bei mir nicht.
@Finalspace die Lösung hab ich noch nicht ganz verstanden, kurz nochmal gefragt:
- ist der Unterschied zwischen "Header-Datei" und "Single-Header-File" eine. .h ohne entsprechende .cpp ? wenn ja dann hab ich das sogar so im Test.
Also in der headertest.h steht jetzt:
Code:
#if !defined(XXX_IMPLEMENTED) && defined(XXX_IMPLEMENTATION)
#define XXX_IMPLEMENTED 1
int testvar = 7;
#endif
in der main.cpp:
Code:
#define XXX_IMPLEMENTED
#define XXX_IMPLEMENTATION
#include headertest.h

int testvar = 7; wird so noch nicht kompiliert

ps: hat man eigentlich Einfluss auf das Thema "die Header-Datei eine eigene Translation kompiliert wird - separat" gibts da ein flag oder so? (denn bei @coolmodi scheint der gleiche code zu klappen)
 
Jetzt auf dein Beispiel bezogen: Wenn ich jetzt nicht total daneben liege, dann ergibt deine Bedingung #if !defined(XXX_IMPLEMENTED) && defined(XXX_IMPLEMENTATION) auch false. Dementsprechend wird int test = 7; auch nicht mit kompiliert.
XXX_IMPLEMENTED darf eben nicht definiert sein :confused_alt:
 
  • Gefällt mir
Reaktionen: T_55
Ok sorry ich hätte richtig kompilieren sollen, denn die IDEs zeigen den Code als inaktiv an obwohl er aktiv ist...
Habe nochmal probiert und folgendes reicht:
main.cpp
Code:
#define TEST
#include headertest.h
headertest.h
Code:
#if !defined(egalwashiersteht) && defined(TEST)
int testvar = 7;
#endif
so funktioniert es, man darf sich nur nicht vom IDE verschaukeln lassen.
Also die Zeile #define XXX_IMPLEMENTED 1 kann raus und bei der boolischen negierung ist egal was im defined steht.
Hab zwar nicht 100% verstanden warum der Trick mit !()&&() funktioniert aber er funktioniert :)
 
Zurück
Oben