Аргумент Concat Macro с пространством имен - PullRequest
5 голосов
/ 18 декабря 2009

У меня есть макрос, где один из аргументов является значением перечисления, которое дается без указания области пространства имен. Однако где-то внутри макроса мне нужно получить к нему доступ (очевидно, я должен определить пространство имен там), но я не могу связать имя пространства имен с параметром шаблона. Принимая во внимание следующий пример кода, компилятор жалуется, что pasting :: and Val doesnt give a valid preprocessor token (он прекрасно работает для объединения get и a для getVal).

 namespace TN
 {
    enum Info
    {
        Val = 0
    };
 }

#define TEST(a) TN::Info get ## a(){return TN::##a;}
TEST(Val)

Так есть ли способ заставить эту работу работать без использования другого аргумента и в основном указывать значение, которое будет использоваться дважды (например, #define TEST(a,b) TN::Info get ## a(){return b;})?

Ответы [ 2 ]

10 голосов
/ 18 декабря 2009

## - это оператор вставки токена, то есть он должен создать один токен из нескольких битов токена, и, как говорит компилятор, ::Val - это не один токен, это два токена.

Зачем вам вообще думать, что вам нужен второй ##? Что с этим не так.

#define TEST(a) TN::Info get ## a () { return TN::a; }
3 голосов
/ 18 декабря 2009

Используйте ## только тогда, когда вы хотите объединить два элемента и заставить компилятор обрабатывать результат как один токен (например, идентификатор).

В вашем макросе первое использование ## правильно, так как вы пытаетесь создать идентификатор, вставляя вместе get и содержимое a, но второе использование ## является ложным, так как вы просто хотите сделать идентификатор из содержимого a, и оператор :: является отдельной сущностью для этого. GCC будет жаловаться на это (хотя MSVC ++ справляется).

#define TEST(a) TN::Info get ## a(){return TN::a;}

должно работать.

...