jeudi 12 août 2021

Enable a function if a template parameter has a specific operator

I'm currently implementing an optional type like the one in java and it would be nice if i could automatically implement all the operators that are present in the type that the optional wraps.

Example:

#include <optional>

struct nullopt_t
{
};

template <typename T>
class Optional
{
    // implementing the usual optional functionality
    // for the example just using std::optional
private:
    std::optional<T> stdOptional = std::nullopt_t{};

public:
    Optional(nullopt_t empty)
    {
        stdOptional = std::nullopt_t{};
    }

    Optional(T value) : stdOptional(std::make_optional(value)) {}

    template <typename R, typename Other, typename enabled = void>
    Optional<R> operator+(Other other);

    template <typename R, typename Other, std::enable_if</* some magic */>::value>
    Optional<R> operator+(Other other)
    {
        if (stdOptional)
            return Optional<R>(stdOptional.value() + other);
        return nullopt_t{};
    }

    // ...
};

struct Foo
{
};

struct Bar
{
   Foo operator+(Bar other);
};

int main()
{
    Optional<int> intOp{1};
    Optional<int> result = intOp + 1; // should work

    Optional<Bar> barOp{Bar{}};
    Optional<Foo> resultBar = barOp + Foo{}; // should also work

    Optional<Foo> fooOp{Foo{}};
    Optional<Foo> resultFoo = fooOp + Foo{}; // should not work
}

/* some magic */ would check if the operator operator+ has been implemented in T.

I would then apply /* some magic */ for each operator that is available in c++ such that you can simply use them instead of checking the if your self or passing some lambda that does the same thing.

Aucun commentaire:

Enregistrer un commentaire