Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. Syntax Error with Q_ASSERT
Forum Updated to NodeBB v4.3 + New Features

Syntax Error with Q_ASSERT

Scheduled Pinned Locked Moved Solved C++ Gurus
25 Posts 5 Posters 9.4k Views 5 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mrjjM Offline
    mrjjM Offline
    mrjj
    Lifetime Qt Champion
    wrote on last edited by mrjj
    #2

    Hi
    It's like it sees it as 2 params. ?!?
    It's not Q_ASSERT fault ( it seems) as any macro suffer from this.

    #define MACRO(cond) (true)
    MainWindow::~MainWindow()
    {
    MACRO( std::is_same<int, int>::value );

    gives me
    error: macro "MACRO" passed 2 arguments, but takes just 1
    MACRO( std::is_same<int, int>::value );
    ^

    (5.7, mingw)

    So it seems its just macro and templates and a stupid preprocessor
    http://stackoverflow.com/questions/9416635/using-commas-inside-a-macro-without-parenthesis-how-can-i-mix-and-match-with-a
    http://stackoverflow.com/questions/8942912/how-to-pass-multi-argument-templates-to-macros

    ? 1 Reply Last reply
    3
    • mrjjM mrjj

      Hi
      It's like it sees it as 2 params. ?!?
      It's not Q_ASSERT fault ( it seems) as any macro suffer from this.

      #define MACRO(cond) (true)
      MainWindow::~MainWindow()
      {
      MACRO( std::is_same<int, int>::value );

      gives me
      error: macro "MACRO" passed 2 arguments, but takes just 1
      MACRO( std::is_same<int, int>::value );
      ^

      (5.7, mingw)

      So it seems its just macro and templates and a stupid preprocessor
      http://stackoverflow.com/questions/9416635/using-commas-inside-a-macro-without-parenthesis-how-can-i-mix-and-match-with-a
      http://stackoverflow.com/questions/8942912/how-to-pass-multi-argument-templates-to-macros

      ? Offline
      ? Offline
      A Former User
      wrote on last edited by
      #3

      @mrjj Thank you! That's really pretty stupid.

      mrjjM kshegunovK 2 Replies Last reply
      1
      • ? A Former User

        @mrjj Thank you! That's really pretty stupid.

        mrjjM Offline
        mrjjM Offline
        mrjj
        Lifetime Qt Champion
        wrote on last edited by
        #4

        @Wieland
        Yeah, i know templates are pure compiler stage
        but one should think preprocess at least accepts valid
        syntaxes :)
        Luckily the () fix is not super ugly.

        1 Reply Last reply
        1
        • ? A Former User

          @mrjj Thank you! That's really pretty stupid.

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #5

          @mrjj said in Syntax Error with Q_ASSERT:

          one should think preprocess at least accepts valid
          syntaxes

          Why should anyone think that?

          @Wieland said in Syntax Error with Q_ASSERT:

          That's really pretty stupid.

          The preprocessor is basically a copy-paste-made-easy, it's a very, very simple program. It does string replacements only, it cares not for any syntax or any language for that matter. You can run the preprocessor independently of the compiler (whether it's C, C++, Java, FORTRAN or w/e), and actually some fortran code (used with gfortran) makes use of the gcc's preprocessor.

          Read and abide by the Qt Code of Conduct

          ? 1 Reply Last reply
          1
          • kshegunovK kshegunov

            @mrjj said in Syntax Error with Q_ASSERT:

            one should think preprocess at least accepts valid
            syntaxes

            Why should anyone think that?

            @Wieland said in Syntax Error with Q_ASSERT:

            That's really pretty stupid.

            The preprocessor is basically a copy-paste-made-easy, it's a very, very simple program. It does string replacements only, it cares not for any syntax or any language for that matter. You can run the preprocessor independently of the compiler (whether it's C, C++, Java, FORTRAN or w/e), and actually some fortran code (used with gfortran) makes use of the gcc's preprocessor.

            ? Offline
            ? Offline
            A Former User
            wrote on last edited by A Former User
            #6

            @kshegunov The preprocessor is part of the C++ language specification and I would expect that, besides all the other smart things it also can do, it is able to handle such situations in a sane way. Anyways, I got used to C++ coming up with nasty surprises.

            Edit: Next time maybe better Write in Go ;-)

            kshegunovK 1 Reply Last reply
            1
            • ? A Former User

              @kshegunov The preprocessor is part of the C++ language specification and I would expect that, besides all the other smart things it also can do, it is able to handle such situations in a sane way. Anyways, I got used to C++ coming up with nasty surprises.

              Edit: Next time maybe better Write in Go ;-)

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by
              #7

              @Wieland said in Syntax Error with Q_ASSERT:

              The preprocessor is part of the C++ language specification

              It is? I've never known that.

              Anyways, I got used to C++ coming up with nasty surprises.

              Eh, yeah. More syntax means more pitfalls. But tell that to the standards committee ... as you said, just write in Go! ;)

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              1
              • Chris KawaC Offline
                Chris KawaC Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on last edited by
                #8

                The preprocessor only understands ( and , in this case (as it's a pre processor i.e. no symbols, namespaces or templates exist at this point), so this is basically parsed as Q_ASSERT(STUFF, OTHER_STUFF); When you put the extra parentheses it becomes Q_ASSERT(STUFF_IN_PARENTHESES).

                Here's a cute gotcha for the extra parentheses trick:
                Because the general rules for type deduction in c++ were pretty boring, c++11 brought such wonders as decltype to make it more fun:

                int foo;
                bool nudge_nudge_wink_wink = std::is_same<decltype(foo), decltype((foo))>::value; //gives "false"... obviously :P
                

                This marvel is sponsored by the fact that foo is an lvalue and (foo) is an expression ;)

                So if in your macro you happen to try to deduce the type of the expression passed to it you might have a joyful debugging session.
                This is one such super-simplified pattern commonly found in macro based property systems:

                #define FOO(bar, bazz) decltype(bar) hello = bazz;
                
                int foo;
                
                FOO(foo, 42); //works fine
                FOO((foo), 42); //error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
                

                @kshegunov
                C++ standard includes C standard by reference. One of the talks at this year's CppCon mentioned that there was a cleanup effort in C++17 made to remove some of the more obscure or irrelevant C headers.

                ? kshegunovK 2 Replies Last reply
                5
                • Chris KawaC Chris Kawa

                  The preprocessor only understands ( and , in this case (as it's a pre processor i.e. no symbols, namespaces or templates exist at this point), so this is basically parsed as Q_ASSERT(STUFF, OTHER_STUFF); When you put the extra parentheses it becomes Q_ASSERT(STUFF_IN_PARENTHESES).

                  Here's a cute gotcha for the extra parentheses trick:
                  Because the general rules for type deduction in c++ were pretty boring, c++11 brought such wonders as decltype to make it more fun:

                  int foo;
                  bool nudge_nudge_wink_wink = std::is_same<decltype(foo), decltype((foo))>::value; //gives "false"... obviously :P
                  

                  This marvel is sponsored by the fact that foo is an lvalue and (foo) is an expression ;)

                  So if in your macro you happen to try to deduce the type of the expression passed to it you might have a joyful debugging session.
                  This is one such super-simplified pattern commonly found in macro based property systems:

                  #define FOO(bar, bazz) decltype(bar) hello = bazz;
                  
                  int foo;
                  
                  FOO(foo, 42); //works fine
                  FOO((foo), 42); //error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
                  

                  @kshegunov
                  C++ standard includes C standard by reference. One of the talks at this year's CppCon mentioned that there was a cleanup effort in C++17 made to remove some of the more obscure or irrelevant C headers.

                  ? Offline
                  ? Offline
                  A Former User
                  wrote on last edited by
                  #9

                  @Chris-Kawa Thank you for this! Every day a new surprise. Or two.

                  1 Reply Last reply
                  1
                  • Chris KawaC Chris Kawa

                    The preprocessor only understands ( and , in this case (as it's a pre processor i.e. no symbols, namespaces or templates exist at this point), so this is basically parsed as Q_ASSERT(STUFF, OTHER_STUFF); When you put the extra parentheses it becomes Q_ASSERT(STUFF_IN_PARENTHESES).

                    Here's a cute gotcha for the extra parentheses trick:
                    Because the general rules for type deduction in c++ were pretty boring, c++11 brought such wonders as decltype to make it more fun:

                    int foo;
                    bool nudge_nudge_wink_wink = std::is_same<decltype(foo), decltype((foo))>::value; //gives "false"... obviously :P
                    

                    This marvel is sponsored by the fact that foo is an lvalue and (foo) is an expression ;)

                    So if in your macro you happen to try to deduce the type of the expression passed to it you might have a joyful debugging session.
                    This is one such super-simplified pattern commonly found in macro based property systems:

                    #define FOO(bar, bazz) decltype(bar) hello = bazz;
                    
                    int foo;
                    
                    FOO(foo, 42); //works fine
                    FOO((foo), 42); //error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
                    

                    @kshegunov
                    C++ standard includes C standard by reference. One of the talks at this year's CppCon mentioned that there was a cleanup effort in C++17 made to remove some of the more obscure or irrelevant C headers.

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #10

                    @Chris-Kawa
                    Yes, I suppose so, I just never thought about it. I don't often think about what the standard does or doesn't include, but I always thought the preprocessor is just a "common non-standardized extension", the language doesn't require it to function. And seeing that code, which I'm happy to say I understand not one iota of, I must reiterate my despise for C++11. :)

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    1
                    • Chris KawaC Offline
                      Chris KawaC Offline
                      Chris Kawa
                      Lifetime Qt Champion
                      wrote on last edited by
                      #11

                      @kshegunov

                      I must reiterate my despise for C++11. :)

                      There there... <pat on the back> :)

                      kshegunovK 1 Reply Last reply
                      3
                      • Chris KawaC Chris Kawa

                        @kshegunov

                        I must reiterate my despise for C++11. :)

                        There there... <pat on the back> :)

                        kshegunovK Offline
                        kshegunovK Offline
                        kshegunov
                        Moderators
                        wrote on last edited by kshegunov
                        #12

                        C++11 always evokes this feeling in me:

                        and by the way I'm an atheist ... :]

                        Read and abide by the Qt Code of Conduct

                        1 Reply Last reply
                        2
                        • ? Offline
                          ? Offline
                          A Former User
                          wrote on last edited by
                          #13

                          I just came up with something that looks like a solution for this to me. What do guys think?

                          #if !defined(MY_ASSERT)
                          #  ifndef QT_NO_DEBUG
                          #    define MY_ASSERT_FIRST_ARGUMENT(A, ...) A
                          #    define MY_ASSERT(...) ((!MY_ASSERT_FIRST_ARGUMENT(__VA_ARGS__)) ? qt_assert(#__VA_ARGS__,__FILE__,__LINE__) : qt_noop())
                          #  else
                          #    define MY_ASSERT(...) qt_noop()
                          #  endif
                          #endif
                          
                          mrjjM 1 Reply Last reply
                          0
                          • ? A Former User

                            I just came up with something that looks like a solution for this to me. What do guys think?

                            #if !defined(MY_ASSERT)
                            #  ifndef QT_NO_DEBUG
                            #    define MY_ASSERT_FIRST_ARGUMENT(A, ...) A
                            #    define MY_ASSERT(...) ((!MY_ASSERT_FIRST_ARGUMENT(__VA_ARGS__)) ? qt_assert(#__VA_ARGS__,__FILE__,__LINE__) : qt_noop())
                            #  else
                            #    define MY_ASSERT(...) qt_noop()
                            #  endif
                            #endif
                            
                            mrjjM Offline
                            mrjjM Offline
                            mrjj
                            Lifetime Qt Champion
                            wrote on last edited by
                            #14

                            @Wieland
                            where is the docs? ;)
                            Looks cool. its cryptic enough that it might actually work :)

                            K 1 Reply Last reply
                            0
                            • mrjjM mrjj

                              @Wieland
                              where is the docs? ;)
                              Looks cool. its cryptic enough that it might actually work :)

                              K Offline
                              K Offline
                              koahnig
                              wrote on last edited by
                              #15

                              @mrjj said in Syntax Error with Q_ASSERT:

                              Looks cool. its cryptic enough that it might actually work :)

                              :D :D

                              Vote the answer(s) that helped you to solve your issue(s)

                              1 Reply Last reply
                              1
                              • ? Offline
                                ? Offline
                                A Former User
                                wrote on last edited by A Former User
                                #16

                                It's almost the same as the current implementation of Q_ASSERT, just with a variadic macro. So it's C++11 only.

                                1 Reply Last reply
                                0
                                • Chris KawaC Offline
                                  Chris KawaC Offline
                                  Chris Kawa
                                  Lifetime Qt Champion
                                  wrote on last edited by Chris Kawa
                                  #17

                                  @mrjj good one :)
                                  @Wieland Could you explain how it is suppose to work? From what I can decrypt it just checks the first argument passed, so for your original exampleMY_ASSERT(std::is_same<int, int>::value); it would expand to something like ((!std::is_same<int) ? ... which doesn't make much sense? Or am I missing something?

                                  Btw. I get compiler errors for this:
                                  with gcc: in definition of macro MY_ASSERT_FIRST_ARGUMENT wrong number of template arguments (1, should be 2)
                                  with clang: error: expected > MY_ASSERT(std::is_same<int, int>::value);
                                  it compiles in VS2015 U3 although their macro expansion is broken to bits so I wouldn't trust it does what it should.

                                  ? 2 Replies Last reply
                                  1
                                  • Chris KawaC Chris Kawa

                                    @mrjj good one :)
                                    @Wieland Could you explain how it is suppose to work? From what I can decrypt it just checks the first argument passed, so for your original exampleMY_ASSERT(std::is_same<int, int>::value); it would expand to something like ((!std::is_same<int) ? ... which doesn't make much sense? Or am I missing something?

                                    Btw. I get compiler errors for this:
                                    with gcc: in definition of macro MY_ASSERT_FIRST_ARGUMENT wrong number of template arguments (1, should be 2)
                                    with clang: error: expected > MY_ASSERT(std::is_same<int, int>::value);
                                    it compiles in VS2015 U3 although their macro expansion is broken to bits so I wouldn't trust it does what it should.

                                    ? Offline
                                    ? Offline
                                    A Former User
                                    wrote on last edited by
                                    #18

                                    @Chris-Kawa Damn, I only tested it with MSVC and it works there :-(

                                    1 Reply Last reply
                                    1
                                    • Chris KawaC Chris Kawa

                                      @mrjj good one :)
                                      @Wieland Could you explain how it is suppose to work? From what I can decrypt it just checks the first argument passed, so for your original exampleMY_ASSERT(std::is_same<int, int>::value); it would expand to something like ((!std::is_same<int) ? ... which doesn't make much sense? Or am I missing something?

                                      Btw. I get compiler errors for this:
                                      with gcc: in definition of macro MY_ASSERT_FIRST_ARGUMENT wrong number of template arguments (1, should be 2)
                                      with clang: error: expected > MY_ASSERT(std::is_same<int, int>::value);
                                      it compiles in VS2015 U3 although their macro expansion is broken to bits so I wouldn't trust it does what it should.

                                      ? Offline
                                      ? Offline
                                      A Former User
                                      wrote on last edited by A Former User
                                      #19

                                      @Chris-Kawa My idea hope was that the preprocessor would be smarter when I confront it with a variadic macro.

                                      1 Reply Last reply
                                      0
                                      • Chris KawaC Offline
                                        Chris KawaC Offline
                                        Chris Kawa
                                        Lifetime Qt Champion
                                        wrote on last edited by
                                        #20

                                        @Wieland I don't think it works. It just compiles ;)
                                        Well you could use something simpler:

                                        define MY_ASSERT(...) (!(__VA_ARGS__) ? qt_assert(#__VA_ARGS__,__FILE__,__LINE__) : qt_noop())
                                        

                                        and that should be ok, but it has the same drawback I described earlier - it changes the expression it tests by adding extra () around it. Admittedly it's not a big deal and it should work as expected most of the time.

                                        ? 1 Reply Last reply
                                        0
                                        • Chris KawaC Chris Kawa

                                          @Wieland I don't think it works. It just compiles ;)
                                          Well you could use something simpler:

                                          define MY_ASSERT(...) (!(__VA_ARGS__) ? qt_assert(#__VA_ARGS__,__FILE__,__LINE__) : qt_noop())
                                          

                                          and that should be ok, but it has the same drawback I described earlier - it changes the expression it tests by adding extra () around it. Admittedly it's not a big deal and it should work as expected most of the time.

                                          ? Offline
                                          ? Offline
                                          A Former User
                                          wrote on last edited by A Former User
                                          #21

                                          @Chris-Kawa Yes it works; funny that it doesn't work for you. Who knows why..

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved