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.3k 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.
  • 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
                          • Chris KawaC Offline
                            Chris KawaC Offline
                            Chris Kawa
                            Lifetime Qt Champion
                            wrote on last edited by
                            #22

                            @Wieland Maybe I messed up something. http://ideone.com/XKJUnV

                            ? 1 Reply Last reply
                            0
                            • Chris KawaC Chris Kawa

                              @Wieland Maybe I messed up something. http://ideone.com/XKJUnV

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

                              @Chris-Kawa Ha! Just found out that #define FIRST(A, ...) A doesn't work as expected (with MSVC): It doesn't give us the first argument only, instead it just gives all arguments (like __VA_ARGS__). Maybe I'm wrong here again, but that looks like a bug in MSVC to me and it also explains why the code works.

                              Edit: Maybe it's really a bug in VC's preprocessor, at least someone on SO says so. And the workaround he presents actually seems to fix it, so now my code doesn't compile with MSVC anymore.

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

                                Thanks everyone for watching me stumbling around like a clown :)

                                mrjjM 1 Reply Last reply
                                2
                                • ? A Former User

                                  Thanks everyone for watching me stumbling around like a clown :)

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

                                  @Wieland
                                  Well to be fair, fooling around with Variadic Macros takes more balls than entertaining
                                  clueless children - so it was educational to see that even in 2016, you cannot trust the preprocessor
                                  to work the same across compilers. :)

                                  1 Reply Last reply
                                  1

                                  • Login

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