Code: Select all
#if defined(__has_include) && __has_include("header.h")
#include "header.h"
#else
#include "backup-header.h"
#endif
Die Dokumentation von GCC schlägt etwa Folgendes vor:
Code: Select all
#if defined __has_include
# if __has_include ()
# include
# endif
#endif
Das Problem dabei ist, dass es schwierig wird, den Zweig #else zu verketten. Wenn wir es an unser Beispiel anpassen würden, müssen wir ein zusätzliches Makro definieren, um zu verfolgen, ob __has_include erfolgreich war, was den Code viel ausführlicher macht:
Code: Select all
#ifdef __has_include
#if __has_include("header.h")
#include "header.h"
#define HAS_INCLUDE_HEADER_H
#endif
#endif
#ifndef HAS_INCLUDE_HEADER_H
#include "backup-header.h"
#endif
#undef HAS_INCLUDE_HEADER_H
Code: Select all
// This part can be done once in a common header
#ifdef __has_include
#define MY_HAS_INCLUDE(Arg) __has_include(Arg)
#else
#define MY_HAS_INCLUDE(Arg) 0
#endif
#if MY_HAS_INCLUDE("header.h")
#include "header.h"
#else
#include "backup-header.h"
#endif
Der Ausdruck, der die bedingte Einbeziehung steuert, muss ein ganzzahliger konstanter Ausdruck sein, mit der Ausnahme, dass Bezeichner (einschließlich derjenigen, die lexikalisch mit Schlüsselwörtern identisch sind) wie unten beschrieben interpretiert werden und null oder mehr definierte Makroausdrücke und/oder has-include-expressions und/oder has-attribute-expressions enthalten können unäre Operatorausdrücke.
...
Die Anweisungen #ifdef, #ifndef, #elifdef und #elifndef sowie der definierte bedingte Einschlussoperator behandeln __has_include und __has_cpp_attribute so, als wären sie die Namen definierter Makros. Die Bezeichner __has_include und __has_cpp_attribute dürfen in keinem Kontext erscheinen, der nicht in diesem Unterabschnitt erwähnt wird.
https://timsong-cpp.github.io/cppwp/n4950/cpp.cond
(C23 hat eine im Wesentlichen identische Klausel)
Mein Verständnis ist, dass dies besagt, dass „
Code: Select all
__has_includeCode: Select all
#elifIch habe über ein paar Problemumgehungen nachgedacht und mich gefragt, ob eine davon standardkonform ist und funktionieren würde.
(A) Die Definition von MY_HAS_INCLUDE als Makro ohne Argumente anstelle eines Makros, das ein Argument akzeptiert, bringt Clangs zum Schweigen Warnung, aber ich bezweifle, dass dies tatsächlich gültig ist, da wir den Ausdruck __has_include immer noch außerhalb einer #if-Bedingung schreiben. Besteht eine Chance, dass dies standardkonform ist?
Code: Select all
// This part can be done once in a common header
#ifdef __has_include
#define MY_HAS_INCLUDE __has_include
#else
#define HAS_INCLUDE_STUB(Arg) 0
#define MY_HAS_INCLUDE HAS_INCLUDE_STUB
#endif
#if MY_HAS_INCLUDE("header.h")
#include "header.h"
#else
#include "backup-header.h"
#endif
Code: Select all
// This part can be done once in a common header
#ifdef __has_include
#define IF_HAS_INCLUDE_SUPPORTED(Arg) Arg
#else
#define IF_HAS_INCLUDE_SUPPORTED(Arg) 0
#endif
#if IF_HAS_INCLUDE_SUPPORTED(__has_include("header.h"))
#include "header.h"
#else
#include "backup-header.h"
#endif
Code: Select all
// This part can be done once in a common header
#ifdef __has_include
#define HAS_INCLUDE_TAKE_EMPTY_PAREN()
#define PRE_HAS_INCLUDE
#define POST_HAS_INCLUDE HAS_INCLUDE_TAKE_EMPTY_PAREN (
#else
#define HAS_INCLUDE_CONSUMER(Arg) 0
#define PRE_HAS_INCLUDE HAS_INCLUDE_CONSUMER (
#define POST_HAS_INCLUDE
#endif
#if PRE_HAS_INCLUDE __has_include("header.h") POST_HAS_INCLUDE )
#include "header.h"
#else
#include "backup-header.h"
#endif
Code: Select all
// This part can be done once in a common header
#ifdef __has_include
#define IF_HAS_INCLUDE_SUPPORTED
#else
#define IF_HAS_INCLUDE_SUPPORTED(Arg) (0)
#endif
#if IF_HAS_INCLUDE_SUPPORTED(__has_include("header.h"))
#include "header.h"
#else
#include "backup-header.h"
#endif
Code: Select all
// This part can be done once in a common header
#ifndef __has_include
#define __has_include(Arg) 0
#endif
#if __has_include("header.h")
#include "header.h"
#else
#include "backup-header.h"
#endif
Welche meiner vorgeschlagenen Problemumgehungen (oder andere Lösungen, die ähnlich funktionieren) sind in C/C++ gültig, wenn überhaupt? Das Beispiel, das ich für die Verkettung von if-else gegeben habe, ist lediglich ein Beispiel. Ich interessiere mich für allgemeine Techniken zur Verwendung von __has_include in #if-Bedingungen, wenn es definiert sein kann oder nicht.
Mobile version