1. 23
  1.  

  2. 3

    That starts out seeming like a good idea and just ends up as one hell of a mess. It’s a shame it made it into the standard in this bodgy form.

    1. 2

      It was actually almost guaranteed to end up like this. After all, the testing ground for c++ (boost) had variant defined exactly like that for years.

    2. 3

      I used boost::any and all I can say is that it works. This and std::variant are not the prettiest solutions, but because it is in standard, it is better than no solution. I very like simplicity of QVariant from Qt, but syntax for adding custom types leads to the same problems as it is in boost::any. I hope that in a close future, c++ will get real pattern matching syntax and then all explicit conversions to proper type will be only nightmare from the past.

      1. 4

        So I’ve only spent like two minutes looking, but I think you can also do pattern matching with switch(variant.index()) if you like.

        1. 6

          That would be non-exhaustive at compile-time

          1. 3

            What the author’s going for is selecting an alternative and getting the value out should be the same operation, so you can’t hit a runtime type error between checking the alternative and unboxing it.

            1. 1

              A guarantee that the type won’t change in a concurrent environment is going to require a lot more machinery I think. There’s accessors to get pointers to the value. And in other cases, the value itself may be a pointer. If the type can change at any time, those pointers will invalidated. If you want the borrow checker, it’s over there I guess, but I didn’t really get the sense that the author wants atomic selectors.

              1. 3

                I was unclear there. By “the same operation,” I just mean that selecting and unboxing shouldn’t be separate points in the code. I’m not about to argue that variant needs to be concurrent.

                What I mean is just that in

                select (boink.index()) {
                case 0: int val = get<0>(boink); 
                    ...
                }
                

                you’re mentioning the index twice, and if you mistype one or the other you’ll only find out at runtime.

                1. 1

                  Oh, I see. Yeah, you could do switch ((idx = boink.index())) (always another workaround) but it is backtreading.

            2. 2

              Then you’re writing exactly the same code as you would with a tagged union, except it’s actually worse because you don’t get -Wswitch. (warning: enumeration value ‘ASDF’ not handled in switch [-Wswitch])

              1. 2

                Well, it’s solve the problem that the tag and the value diverge because you forget to update one. Guess you get to choose which is worse. It seems the return type of index could be an enum (though obviously they didn’t do that). Not sure how much more difficult that would have been.