jeudi 8 janvier 2015

User-defined move constructor for member of lvalue reference type

I'm playing around with move semantics on a compiler, which has rvalue references but does not support defaulted move constructors. I would like to generate something like the wrapper class below, which works even if the template parameter is an lvalue reference. However, this straightforward approach does not compile because it tries to initialize an int& from an int.



#define USER_DEFINED 0

template <typename T>
struct Wrapper
{
Wrapper(T t)
: m_t(t)
{
}

Wrapper(const Wrapper&) = delete;
Wrapper& operator=(const Wrapper&) = delete;

#if USER_DEFINED
Wrapper(Wrapper&& w)
: m_t(std::move(w.m_t))
{
}
#else
Wrapper(Wrapper&&) = default;
#endif

private:
T m_t;
};

int main()
{
int i = 0;
Wrapper<int&> w1 = Wrapper<int&>(i);
Wrapper<std::string> w2 = Wrapper<std::string>("text");
}


The obvious solution would be to have two move constructors, one for lvalue references and one for all other types. Something like this for example:



template <typename U = T>
Wrapper(typename std::enable_if<!std::is_lvalue_reference<U>::value, Wrapper>::type&& w)
: m_t(std::move(w.m_t))
{
}

template <typename U = T>
Wrapper(typename std::enable_if<std::is_lvalue_reference<U>::value, Wrapper>::type&& w)
: m_t(w.m_t)
{
}


So is this the way to go? Maybe the expression inside the enable_if<> should be more generic? Or can I use something different from std::move() and have one single constructor for all types?


Aucun commentaire:

Enregistrer un commentaire