Verwenden Sie static_assert, um die an das Makro übergebenen Typen zu überprüfen

Lesezeit: 7 Minuten

Verwenden Sie static assert um die an das Makro ubergebenen Typen
Matt Joiner

Leider habe ich mehrere Makros von der ursprünglichen Version meiner Bibliothek übrig, die ziemlich verrücktes C verwendet. Insbesondere habe ich eine Reihe von Makros, die erwarten, dass bestimmte Typen an sie übergeben werden. Ist es möglich, etwas in der Art zu tun:

static_assert(decltype(retval) == bool);

Und wie? Gibt es clevere Alternativen?

Ja, mir ist bewusst, dass Makros schlecht sind. Ich bin mir bewusst, dass C++ nicht C ist usw.

Update0

Hier ist etwas zugehöriger Code, und das Quelldatei. Vorschläge sind willkommen. Die ursprüngliche Frage bleibt dieselbe.

  • Nachdem ich die eigentlichen Makros gesehen habe, würde ich stark schlagen vor, modernes C++-Design zu lesen oder [More] Außergewöhnliches C++.

    – MSalters

    28. Okt ’10 um 11:39

  • @MSalters: Ich kann mir nicht vorstellen, wie C++ implizite Alternativen zu meinem Ein- / Ausstieg bieten kann, aber ich werde es mir ansehen. Beachten Sie auch, dass das Schreiben eines FS sehr unmeta ist. Mein Ziel ist es nicht, ein großartiges C++-Framework zu erstellen.

    – Matt Joiner

    31. Okt ’10 um 2:30

  • Sie legen ein Objekt beim Betreten auf den Stapel; Jedes Verlassen des Bereichs zerstört das Objekt. So wird beim Betreten der ctor aufgerufen und beim Verlassen der dtor. Der automatische dtor-Aufruf ist besonders nützlich, wir wissen aus der Geschichte, dass typische Programmierer das Makro bei ~5% aller Exits einer Funktion verpassen.

    – MSalters

    2. November ’10 um 9:21

Verwenden Sie static assert um die an das Makro ubergebenen Typen
Matt Joiner

Ich fand dies mit dem Vorschlag von @UncleBens am saubersten:

#include <type_traits>

static_assert(std::is_same<decltype(retval), bool>::value, "retval must be bool");

  • Was ist das c++03-Äquivalent?

    – balki

    31. Okt ’12 um 9:20

  • @balki: Einfach auf C++11 aktualisieren. C++ ist schon schlimm genug, mach es dir nicht noch schlimmer 🙂

    – Matt Joiner

    2. November ’12 um 13:27

  • Beim Benutzen std::is_same, sicher sein zu #include <type_traits>.

    – Jim Garnison

    12. März ’14 um 23:08

  • was ist mit const/reference Qualifiern?

    – einbinden

    10. Dezember ’15 um 9:26

  • @einpoklum-reinstateMonica Sie können verwenden std::remove_const, std::remove_reference usw. C++20 hat auch std::remove_cvref.

    – Dino

    18. November 19 um 13:14 Uhr


Verwenden Sie static assert um die an das Makro ubergebenen Typen
Armen Tsirunyan

Haftungsausschluss: Dies ist eine schlechte Antwort, es gibt definitiv weitaus bessere Lösungen. Nur ein Beispiel 🙂

Es ist sicherlich bereits implementiert, aber es ist trivial, es selbst zu implementieren;

template <class T1, class T2> struct CheckSameType; //no definition
template <class T> struct CheckSameType<T,T>{}; //

template <class T1, class T2>
AssertHasType(T2)
{
   CheckSameType<T1, T2> tmp; //will result in error if T1 is not T2
}

So zu verwenden:

AssertHasType<bool>(retval);

Alternative (von GMan vorgeschlagen):

template <class T1, class T2> struct SameType
{
    enum{value = false};
}
template <class T> struct SameType<T,T>
{
    enum{value = true};
}; 

Zu verwenden wie

static_assert(SameType<decltype(retval), bool>::value);

  • Keine schlechte Antwort / kein schlechtes Konzept, obwohl ich es nicht verstehe AssertHasType und die folgenden Zeilen syntaktisch. Ich würde jedoch empfehlen, Metafunktionen und ein statisches Assert-Dienstprogramm zu erstellen, das zwei wiederverwendbare Dienstprogramme bereitstellt, die kombiniert werden können, um den beabsichtigten Effekt zu erzielen, anstatt eine benutzerdefinierte Prüfung pro Bedingung vorzunehmen.

    – GManNickG

    26. Okt ’10 bei 8:51

  • Oder verwenden Sie is_same von dem type_traits Header (ich hoffe, er ist mit VC10 verfügbar).

    – Onkel Bens

    26. Okt ’10 um 15:50

Es scheint, dass Sie brauchen decltype weil Sie einen Ausdruck haben, aber einen Typ überprüfen möchten. Dafür gibt es jetzt schon genug Möglichkeiten (C++03). Um zum Beispiel einen bool zu überprüfen

inline void mustBeBool(bool) { }
template<typename T> inline void mustBeBool(T t) { & (&t); } // Takes address of rvalue (&t)

// Use:
#define DifficultMacro(B) do { mustBeBool(B); foo(B); } while (false)

  • Für Robustheit auf Boost-Level benötigen Sie ein address_of Vorlage, um die Idioten zu fangen, die unary überladen haben T::operator&()

    – MSalters

    26. Okt ’10 um 14:04

Verwenden Sie static assert um die an das Makro ubergebenen Typen
Gabriel Staples

Wenn dir das wichtig ist const und volatile Qualifikanten und möchten sicherstellen, dass die const und volatile Teile der Typen stimmen auch genau mit dem Typ überein, mit dem Sie vergleichen, machen Sie es wie @Matt Joiner sagt:

#include <type_traits>

static_assert(std::is_same<decltype(my_variable), uint64_t>::value, 
              "type must be `uint64_t`"); 

Ich interessiere dich NICHT const, und möchten einfach sicherstellen, dass der Typ ein bestimmter Typ ist, ohne Rücksicht auf const, gehen Sie stattdessen wie folgt vor. Beachten Sie, dass std::remove_const<>::type wird hier benötigt:

static_assert(std::is_same<std::remove_const<decltype(my_variable)>::type, uint64_t>::value, 
              "type must be `uint64_t` OR `const uint64_t`");   

Das gleiche gilt für volatile. Falls dir das egal ist volatile Teil des Typs entweder, Sie können es ignorieren mit std::remove_volatile<>::type:

static_assert(std::is_same<std::remove_volatile<decltype(my_variable)>::type, uint64_t>::value, 
              "type must be `uint64_t` OR `volatile uint64_t`");

Wenn dir das egal ist const ODER volatile, du kannst sie beide mit entfernen std::remove_cv<>::type:

static_assert(std::is_same<std::remove_cv<decltype(my_variable)>::type, uint64_t>::value, 
              "type must be `uint64_t` OR `const uint64_t` OR `volatile uint64_t` OR `volatile const uint64_t`");

Beachten Sie auch, dass Sie ab C++17 Folgendes tun können:

  1. std::remove_cv_t<decltype(my_variable)> anstelle von std::remove_cv<decltype(my_variable)>::type, und:
  2. std::is_same_v<some_type, another_type> anstelle von std::is_same<some_type, another_type>::value.

Verweise:

  1. Verwenden Sie static_assert, um die an das Makro übergebenen Typen zu überprüfen
  2. https://en.cppreference.com/w/cpp/types/is_same
  3. https://en.cppreference.com/w/cpp/language/decltype
  4. https://en.cppreference.com/w/cpp/header/type_traits
  5. https://en.cppreference.com/w/cpp/types/remove_cvstd::remove_cv<>, std::remove_const<>, std::remove_volatile<>

Verwandt:

  1. [another answer of mine where I use the above static_assert tricks] Wie man Spannweiten macht
  2. Statische Behauptung in C [my own answer]
  3. So verwenden Sie statisches Assert in C, um die Parametertypen zu überprüfen, die an ein Makro übergeben werden [my own question]
  4. Typüberprüfung von Makroargumenten in C
  5. *****C++ Vorlagentyp auf Zahlen beschränken

Die meisten Makros können ersetzt werden durch inline Funktionen und/oder Vorlagen. Ein typisches Beispiel dafür ist die allzu clevere Argument-Größen-Überprüfung von Posix isnan Makro ist eine Vorlage in C++0x. Oh, schlechtes Beispiel, aber Sie bekommen die Idee.

Die wichtigsten Ausnahmen von dieser Regel sind Makros, die im Wesentlichen eine höhere Ebene implementieren Sprache Merkmale. Zum Beispiel eine intelligentere Ausnahmebehandlung oder Kovarianz oder ein parametrisierter Satz von Deklarationen.

In einigen Fällen können die Makros, die nicht vernünftig ausgedrückt werden können, als inline Funktionen oder Templates, durch eine intelligentere Art der Vorverarbeitung, nämlich die Codegenerierung, ersetzt werden. Dann haben Sie irgendwo ein Skript, das den notwendigen Code generiert. Zum Beispiel ist es möglich, Optionsklassen in reinem C++ mit Makros und Templates zu erstellen, aber es ist umständlich, und als einfacher zu verstehende und vielleicht wartungsfreundlichere Alternative könnte man ein Skript verwenden, das die erforderlichen Klassen gegen Aufpreis generiert Build-Schritte und Umgang mit mehreren Sprachen.

Prost & hth.,

  • Bitte geben Sie einen Grund an, wenn Sie ablehnen. Das hilft anderen zu verstehen, was an einer Antwort nicht stimmt. Alternativ kann es anderen helfen, die Ablehnung zu ignorieren.

    – Prost und hth. – Alf

    27. Okt ’10 um 11:00

  • +1. Nachdem man den Code gesehen hat, wird klar, dass die eigentlichen Makros trivialerweise durch ein Stack-alloziertes Objekt ersetzt werden, was die Zuverlässigkeit und Lesbarkeit dramatisch erhöht. Diese Makros werden für die Protokollierung von Funktionsaufrufen/Rückgaben verwendet.

    – MSalters

    28. Okt ’10 um 11:38

  • Bitte geben Sie einen Grund an, wenn Sie ablehnen. Das hilft anderen zu verstehen, was an einer Antwort nicht stimmt. Alternativ kann es anderen helfen, die Ablehnung zu ignorieren.

    – Prost und hth. – Alf

    27. Okt ’10 um 11:00

  • +1. Nachdem man den Code gesehen hat, wird klar, dass die eigentlichen Makros trivialerweise durch ein Stack-alloziertes Objekt ersetzt werden, was die Zuverlässigkeit und Lesbarkeit dramatisch erhöht. Diese Makros werden für die Protokollierung von Funktionsaufrufen/Rückgaben verwendet.

    – MSalters

    28. Okt ’10 um 11:38

.

215420cookie-checkVerwenden Sie static_assert, um die an das Makro übergebenen Typen zu überprüfen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy