2016-06-25 8 views
10

Angenommen, wir haben eine Implementierung von std::aligned_storage. Ich habe zwei Makros für die Operatoren alignof und alignas definiert.Zu viele Argumente für einen funktionsähnlichen Makroaufruf

#include <iostream> 
#include <cstddef> 

#define ALIGNOF(x) alignof(x) 
#define ALIGNAS(x) alignas(x) 

template<std::size_t N, std::size_t Al = ALIGNOF(std::max_align_t)> 
struct aligned_storage 
{ 
    struct type { 
     ALIGNAS(Al) unsigned char data[N]; 
    }; 
}; 

int main() 
{ 
    // first case 
    std::cout << ALIGNOF(aligned_storage<16>::type); // Works fine 

    // second case 
    std::cout << ALIGNOF(aligned_storage<16, 16>::type); // compiler error 
} 

Im zweiten Fall habe ich den Fehler in dem Titel der Frage (mit Clang, ähnlichen Fehlern mit GCC kompilieren). Der Fehler ist nicht vorhanden, wenn ich die Makros durch alignof bzw. alignas ersetze. Warum ist das?

Bevor Sie beginnen, mich zu fragen, warum ich das tue - die ursprünglichen Makros C++ 98 kompatiblen Code wie __alignof und __attribute__((__aligned__(x))) und die sind Compiler spezifisch, so Makros meine einzige Wahl sind ...

EDIT: Also nach der Frage als doppelt markiert, würde eine zusätzliche Klammer setzen das Problem beheben.

std::cout << ALIGNOF((aligned_storage<16, 16>::type)); // compiler error 

Es tut es nicht. Also, wie würde ich das tun? (Erfüllbare Frage?)

+1

@melpomene, geben wird, die nicht wirklich eine Möglichkeit, um das Problem der Arbeits – chris

+1

Warum? Weil Komma. - Makroexpansion sieht das Komma vor dem syntaktischen Sinn eines anderen Inhalts –

+0

http://stackoverflow.com/questions/679979/how-to-make-a-variadic-macro-variable-number-of-arguments kann hilfreich sein –

Antwort

13

C/C++ - Präprozessor kennt keine C/C++ - Sprachkonstrukte, es ist nur Text-Präprozessor mit eigener Syntax und Regeln. Entsprechend dieser Syntax ist der folgende Code ALIGNOF(aligned_storage<16, 16>::type) der Aufruf des Makros ALIGNOF mit 2 Argumenten (aligned_storage<16 und 16>::type), da in den Klammern ein Komma steht.

Ich würde vorschlagen, dass Sie typedefaligned_storage<16, 16> und verwenden Sie diesen Typ in diesem Makroaufruf.

+0

@melpomene Vielen Dank für die Bearbeitung, ich wusste nicht ** ** funktioniert nicht in '' :) und meine Reaktion war langsamer als deine :) – mvidelgauz

8

Wie bereits erläutert, werden Makroargumente durch Kommata getrennt, die nicht in zusätzlichen Klammern stehen. Es gibt ein paar einfache ish Wege, dies zu umgehen, einige allgemeinere als andere:

  1. Verwenden Sie ein variadische Makro (oder eine entsprechende Compiler-Erweiterung für C++ 98) (live example):

    #define ALIGNOF(...) alignof(__VA_ARGS__) 
    ALIGNOF(aligned_storage<16, 16>::type) 
    
  2. den Anrufer Holen Sie die Anzahl der Argumente und wickeln Sie die Argumente in zusätzlichen Klammern (live example) weitergeben müssen:

    #define ALIGNOF(n, tuple) alignof(BOOST_PP_TUPLE_ENUM(n, tuple)) 
    ALIGNOF(2 (aligned_storage<16, 16>::type)) 
    
  3. Holen Sie sich das ca ller in eine "Sequenz" passieren (live example):

    #define ALIGNOF(seq) alignof(BOOST_PP_SEQ_ENUM(seq)) 
    ALIGNOF((aligned_storage<16)(16>::type)) 
    
  4. Wenn das Argument ein Typ ist, verwenden Sie einen typedef (live example):

    typedef aligned_storage<16, 16>::type storage_t; 
    ALIGNOF(storage_t) 
    

    anzumerken, dass als Templat Aliase vor erstellt werden können, um C++ 11 durch ein struct Templatverbindung und Belichten eines type Mitglied:

    template<int N> 
    struct alias { 
        typedef typename aligned_storage<N, N>::type type; 
    }; 
    
  5. Wenn das Argument kann in Klammern verwendet werden, um den Aufrufer dazu zu bringen, das Argument in Klammern zu schreiben und es direkt zu verwenden. Dies ist bei alignof nicht der Fall.

Verwandte Themen