C++ Logo

std-proposals

Advanced search

[std-proposals] Achieving syntax by another means (std::variant with std::specify_base)

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Sat, 17 Sep 2022 21:58:34 +0100
When we have a 'variant' object such as either of the following two:

        variant< LaserController, DrillController > obj;
        variant< monostate, LaserController, DrillController > obj;

It would be nice if the following statement:

    int error_code = obj->Initialise(5, 2.0);

could be treated by the compiler as though we had actually written:

    int error_code =
        std::visit([&obj]<class U>(U &u)
        {
            if constexpr ( std::same_as<U, std::monostate> )
            {
                throw std::bad_variant_access();

                // The following line never gets executed -- we just
                // have it here to give this lambda function the correct
                // return type when U is 'std::monostate'
                return std::get<1u>(obj).Initialise(5, 2.0);
            }
            else
            {
                return u.Initialise(5, 2.0);
            }
        }, obj);

The GNU compiler already has some compile-time checking in place to
make sure that "LaserController::Initialise" and
"DrillController::Initialise" have the same return type. Here's the
output I got from the g++ compiler when I changed the return type of
"DrillController::Initialise":

        error: static assertion failed: std::visit requires the
visitor to have the same return type for all alternatives of a variant

I've tried messing around with the preprocessor to write a macro to
perform the translation I've written above, but I couldn't pull it
off. I think we would need compiler support for this one.
In the following code snippet, I've introduced a new function
attribute called 'translate', along with a new keyword called
'__translate__'. When you have expression such as the following:

    obj->Method(arg1,arg2,arg3);

, the keyword '__translate__' gets substituted with "Method(arg1,arg2,arg3)".

So the definition of "std::variant" would look something like as follows:

namespace std {
    class variant {
    public:
        [[translate]] auto operator->
        {
               return std::visit([this]<class U>(U &u)
               {
                  if constexpr ( std::same_as<U, std::monostate> )
                  {
                        throw std::bad_variant_access();

                       // The following line never gets executed -- we just
                       // have it here to give this lambda function the correct
                       // return type when U is 'std::monostate'
                       return std::get<1u>(*this). __translate__ ;
                  }
                  else
                  {
                      return u. __translate__ ;
                  }
             }, obj);
        }
    };
}

Received on 2022-09-17 20:58:45