How to use universal references without other type deduction

187 views Asked by At

I'm writing a wrapper class for a class of type inner_t. Can I call the proper constructor (lvalue reference or rvalue reference) for the inner class in the following way?

template<typename S, typename T>
struct u_ref {
};

template<typename S>
struct u_ref<S, const S&> {
    typedef const S& type;
};

template<typename S>
struct u_ref<S, S&&> {
    typedef S&& type;
};

class wrapper_t {
private:
    inner_t data;
public:
    template<typename T>
    wrapper_t(typename u_ref<inner_t,T>::type c_data):
        data(std::forward(c_data)) {
    }
}
2

There are 2 answers

5
Kerrek SB On BEST ANSWER

The standard idiom is this:

Baby's first template:

#include <utility>

struct Foo
{
    Inner child;

    template <typename ...Args>
    Foo(Args &&... args) : child(std::forward<Args>(args)...) { }

    // ...
};

Grown-up version: The problem with the above is that it makes Foo constructible from anything, which is unclean. We must disable overloads that don't make sense.

#include <type_traits>
#include <utility>

struct Foo
{
    Inner child;

    template <typename ...Args,
              typename = typename std::enable_if<std::is_constructible<Inner, Args...>::value>::type>
    Foo(Args &&... args) : child(std::forward<Args>(args)...) { }

    // ...
};

In this manner, the trait std::is_constructible<Foo, Args...> will have the exact same values as std::constructible<Inner, Args...>, rather than being true for everything.

1
dspyz On

After much search, I found this: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

Rather than explicitly invoking the copy constructor, I can get the same result much more simply using pass-by-value:

class wrapper_t {
private:
    inner_t data;
public:
    wrapper_t(inner_t c_data):
        data(std::move(c_data)) {
    }
}