Is it possible to place a macro in a namespace in c++?

前端 未结 5 1026
花落未央
花落未央 2020-12-05 09:55

My application uses another output than the standard output for logging information, which is why I wrote my own Log(), Error(), Panic()

相关标签:
5条回答
  • 2020-12-05 10:33

    #define is a preprocessor directive. The macros are being replaced before anything else apart from removing comments (which means, before compilation). So at the time macros are replaced, the compiler knows nothing about your namespaces.

    As other people state, in your case it will be fine. However, This is how you can get problems:

    namespace A
    {
     void Assert_ (int condition, std::string message, std::string file, int line)
     {
         std::cout << "A";
     }
       #define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
    
    }
    namespace B
    {
     void Assert_ (int condition)
     {
         std::cout << "B";
     }
       #define Assert(a,b) Assert_(a)
    
    }
    
    int main(int argc, char *argv[])
    {
        A::Assert(0,"asdasd");
        B::Assert(0,"asdasd");
    }
    

    So while it looks like the defines are "in the namespaces", they are not, and the last #define will be always be used, which in this case will lead to a compile-time error, because the code in main will be replaced by:

    A::Assert(0);
    B::Assert(0);
    

    instead of

    A::Assert(0,"asdasd", _FILE_, _LINE_);
    B::Assert(0);
    
    0 讨论(0)
  • 2020-12-05 10:53

    No, the preprocessor doesn't care about namespaces at all. In fact, the preprocessor runs, at least conceptually, before the compiler sees anything.

    For myself, I just do a standard ASSERT macro, and expect that no "sane namespace" has something called ASSERT. Problem solved. Should I require a library that has an ASSERT of its own then I can still decide how to deal with this; however, the only library that I'm currently using with its own "assert" calls it BOOST_ASSERT or something like that...

    0 讨论(0)
  • 2020-12-05 10:54

    Yes, and your macro would expand to exactly what you expect.

    Debug::Assert (some_condition, "Some_condition should be true");
    

    would be replaced by

    Debug::Assert_(some_condition, "Some_condition should be true", __FILE__, __LINE__)
    
    0 讨论(0)
  • 2020-12-05 10:58
    namespace Debug
    {
        void Assert_(int condition, std::string message, std::string file, int line);
        #define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
    }
    
    // .... Somewhere where I call the function ....
    Debug::Assert (some_condition, "Some_condition should be true"); 
    

    This specific usage would do exactly what you want, but the Assert macro is in no way part of the Debug namespace... it's exactly as if you'd done:

    namespace Debug
    {
        void Assert_(int condition, std::string message, std::string file, int line);
    }
    
    #define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
    
    // .... Somewhere where I call the function ....
    Debug::Assert (some_condition, "Some_condition should be true"); 
    

    Here, the substitution works not because Assert was in the Debug namespace (it's not in your code or this code, and the preprocessor has no clue what namespaces are about) - it works because Assert is recognised as an identifier for a macro, the substitution of Assert_ is made, then later the compiler proper happens to find there's a Debug::Assert_ So, say you have somewhere later in your translation unit you have some completely unrelated code:

    my_object.Assert(my_functor);
    

    The macro substituion will still kick in to produce a compile-time error saying you have the wrong number of arguments to a macro. Say the unrelated code was instead:

    my_object.Assert(my_functor, "some text");
    

    Then that would be replaced with:

    my_object.Assert_(my_functor, "some text", __FILE__, __LINE__);
    

    (Separately, it's standard practice not to use lower case letters in preprocessor macro names).

    0 讨论(0)
  • 2020-12-05 10:58

    You can try __PRETTY_FUNCTION __ macro to print all the namespaces including function arguments.

    0 讨论(0)
提交回复
热议问题