jeudi 21 septembre 2017

How can I get the result type of a member function applied to a class member in an unevaluated context

I'm not even sure this question's title is correct. What I'm trying to do is fairly gnarly to me so I don't even know how to describe it in a concise manner. Sorry about that.

I have a container of values which are wrapped in some kind of "safe" value class. I need a function that takes a pointer to that container, a reference to one of its member and the following happens:

If the pointer passed is valid, the function returns the value inside the wrapped value.

If the pointer passed is nullptr, the function returns a default-constructed value.

Anyhoo, here some code.

template<typename T>
class Wrapped {
    T t;
public:
    T& operator*() {
        return t;
    }
};

class Container {
public:
    Wrapped<int> i;
    Wrapped<string> s;
};

// Compiler error with R.
// I'd like R to be the type returned by doing operator* on the member that's represented by M.
// I've tried about 50 different versions of declarations to declare the type of R. This one feels like it most closely represents what I'm trying to achieve.
// R should be the T in Wrapped<T>.

template <typename T, typename M, typename R = decltype(declval<M>().operator*())>
R value_or_default(T* object, M member, R default_value = R{})
{
    object ? *((*object).*member) : default_value;
}

Container c;
auto actual_int = value_or_default(&c, &Container::i);    // Returns *(c.i).
auto default_string = value_or_default(nullptr, &Container::s);   // Returns string{}.

Aucun commentaire:

Enregistrer un commentaire