user1447257
user1447257

Reputation:

Perfect forwarding for wrapper classes

I have for example a wrapper class:

template <typename T>
struct Wrapper {
    T t;
};

And some proxy class that takes does something with T:

template <typename T>
struct Proxy {
    T t;
    void operator()() const {/* .... */}
}

Now there is for convenience a method that creates the proxy, and I have written overloaded it for l- and r-value reference:

template <typename T>
Proxy<const T &> createProxy(const Wrapper<T> &w) {return {w.t};}

template <typename T>
Proxy<T> createProxy(Wrapper<T> &&w) {return {std::move(w.t)};}

This of course is just the stripped down code I wanted to use, but to make everything more readable, I want to use some perfect forwarding magic that results in less code making everything a bit more readable:

template <typename Wrapper>
Proxy</* ??? */> createProxy(Wrapper &&w) { /* ??? */ }

So the question is, how can I deduct the l- or r-value type of a member of an l- or r-value type?

Upvotes: 1

Views: 744

Answers (1)

Casey
Casey

Reputation: 42594

std::forward<Wrapper>(w).t has the same value category as w, so all you need to do is return a Proxy with && stripped from decltype((std::forward<Wrapper>(w).t)):

template <typename T>
struct remove_rvalue_reference {
    using type = T;
};

template <typename T>
struct remove_rvalue_reference<T&&> {
    using type = T;
};

template <typename T>
using remove_rvalue_reference_t = typename remove_rvalue_reference<T>::type;

template <typename Wrapper>
auto createProxy(Wrapper&& w) ->
  Proxy<remove_rvalue_reference_t<decltype((std::forward<Wrapper>(w).t))>> {
    return {std::forward<Wrapper>(w).t};
}

Demo at Coliru

Upvotes: 1

Related Questions