2016-06-25 13 views
10

Powiedzmy, że mamy implementację std::aligned_storage. Zdefiniowałem dwa makra dla operatorów alignof i alignas.Zbyt wiele argumentów dostarczonych do wywołania makropoleceń funkcyjnych

#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 
} 

W drugim przypadku pojawia się błąd w tytule pytania (kompilacja z Clang, podobny błąd z GCC). Błąd nie występuje, jeśli zastępuję makra odpowiednio alignof i alignas. Dlaczego tak jest?

Przed rozpoczęciem pyta mnie, dlaczego to robię - oryginalne makra mają 98 kod zgodny C++, takie jak __alignof i __attribute__((__aligned__(x))) a te są specyficzne kompilator, więc makra są moim jedynym wyborem ...

EDYCJA: Tak więc zgodnie z pytaniem oznaczonym jako duplikat dodatkowy zestaw nawiasów rozwiązałby problem.

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

Nie dotyczy. Więc jak miałbym to zrobić? (Pytanie satysfakcjonujące?)

+1

@melpomene, To naprawdę nie daje żadnego sposobu na obejście problemu – chris

+1

Dlaczego? Ponieważ przecinek. - Ekspansja makr widzi przecinek przed ułożeniem syntaktycznego sensu jakiejkolwiek innej zawartości. –

+0

http://stackoverflow.com/questions/679979/how-to-make-a-variadic-macrewar- ny -argumenty mogą być pomocne –

Odpowiedz

13

Procesor C/C++ nie zna żadnych konstrukcji językowych C/C++, jest tylko preprocesorem tekstu z własną składnią i regułami. Zgodnie z tą składnią następujący kod ALIGNOF(aligned_storage<16, 16>::type) jest wywołaniem makra ALIGNOF z 2 argumentami (aligned_storage<16 i 16>::type), ponieważ w nawiasach znajduje się przecinek.

Proponuję Ci typedefaligned_storage<16, 16> i użyj tego typu wewnątrz tego makropolecenia.

+0

@melpomene Dziękuję za edycję, nie wiedziałem ** ** nie działa w '' :) i moja reakcja była wolniejsza niż twoja :) – mvidelgauz

8

Jak wyjaśniono, argumenty makr są oddzielane przecinkami, które nie znajdują się w nawiasach dodatkowych. Istnieje kilka prostych-owski sposoby obejść ten problem, niektóre bardziej ogólne niż inni:

  1. użyć zmiennej liczbie argumentów makro (lub odpowiadające rozszerzenie kompilator C++ 98) (live example):

    #define ALIGNOF(...) alignof(__VA_ARGS__) 
    ALIGNOF(aligned_storage<16, 16>::type) 
    
  2. Get rozmówcę przejść szereg argumentów i owinąć argumenty w dodatkowych nawiasach (live example):

    #define ALIGNOF(n, tuple) alignof(BOOST_PP_TUPLE_ENUM(n, tuple)) 
    ALIGNOF(2 (aligned_storage<16, 16>::type)) 
    
  3. Get CA Muller przejść w „kolejność” (live example)

    #define ALIGNOF(seq) alignof(BOOST_PP_SEQ_ENUM(seq)) 
    ALIGNOF((aligned_storage<16)(16>::type)) 
    
  4. Jeśli argument jest typu stosować typedef (live example)

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

    Należy zauważyć, że na matrycy aliasy można utworzyć przed C++ 11 przez templating struct i odsłaniając element type:

    template<int N> 
    struct alias { 
        typedef typename aligned_storage<N, N>::type type; 
    }; 
    
  5. Jeśli argument można użyć nawiasów, poproś rozmówcę, aby zawinął argument w nawiasach i użył go bezpośrednio. Tak nie jest w przypadku alignof.

Powiązane problemy