Inserting "::" and "Foo" does not give a valid preprocessing token

I would like to add MyNamespace :: to a function defined by a macro:

#define transFunc(func)                                                    \
dimensionedScalar func(const dimensionedScalar& ds)                        \
{                                                                          \
    if (!ds.dimensions().dimensionless())                                  \
    {                                                                      \
        FatalErrorIn(#func "(const dimensionedScalar& ds)")                \
            << "ds not dimensionless"                                      \
            << abort(FatalError);                                          \
    }                                                                      \
                                                                           \
    return dimensionedScalar                                               \
    (                                                                      \
        #func "(" + ds.name() + ')',                                       \
        dimless,                                                           \
        MyNameSpace::##func(ds.value())                                                 \
    );                  

                                               \

      

}

But when I call

transFunc(Foo)

      

the compiler throws the following error:

Inserting "::" and "Foo" does not give a valid preprocessing token

What is wrong with how I chain the tokens above?

+3


source to share


3 answers


##

used to combine two tokens together to make one token. So something like func##1

will expand to a single token func1

.

Using it here, it tries to combine ::

and Foo

and to make one token ::Foo

. As the error says, this is not a valid token. You don't need one token here; you just want to split two tokens:



MyNameSpace::func(ds.value())

      

+6


source


##

works for macros, it is not designed to work in regular code.

You can do it like this:

#define ADD_NAMESPACE(NS,FUNC) NS##::##FUNC

      

Now you can use it like this:

ADD_NAMESPACE(std,cout)<<x1<<ADD_NAMESPACE(std,endl);

      

But you cannot do this:



std ## :: ## cout<<std ## :: ## endl;

      

You just do:

std::cout<<std::endl;

      

EDIT

this example worked with gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC):

#include <iostream>
#define ADD_NAMESPACE(NS,FUNC) NS##::##FUNC
int main()
{
  ADD_NAMESPACE(std,cout)<<"hello world!"<<ADD_NAMESPACE(std,endl);
  return 0;
}

      

+1


source


As others have said, ## concatenates two tokens at (or after) the tokenization stage of compilation:

a##b => (a) ## (b) => (ab)
( possibly invalid, like (::bar) instead of (::), (bar) )

      

Please note: this does not send the concatenated token ids back through the tokenizer, this compilation step has already been completed. What might be useless is that they are now tokens and not raw strings.


How I came (late to the party) here looking for the same information, here is an example of foo.cpp if still doesn't make sense:

#define FOO(a) Something::a

int main()
{
        FOO( bar );
        FOO( cat );

        return 0;
}

      

gcc -E foo.cpp produces

# 1 "foo.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "foo.cpp"



int main()
{
 Something::bar;
 Something::cat;

 return 0;
}

      

+1


source







All Articles