Reputation: 6008
#include <utility>
#include <vector>
#include <cstdint>
template <typename T>
struct Base
{
protected:
Base(T&& data):
data(std::forward(data)){
}
virtual ~Base(){};
public:
T getData() const {return data;}
void setData(T&& data) {
this->data = std::forward(data);
}
private:
T data;
};
struct DerivedA: public Base<int>
{
public:
DerivedA(int data):
Base(std::move(data)){//Should I use std::forward instead of std::move here?
}
};
struct DerivedB: public Base<const std::vector<uint16_t> >
{
public:
DerivedB(const std::vector<uint16_t>& data):
Base(std::move(data)){
}
};
My requirements is to have 0 copying of objects when creating the Derived Classes above. But no matter how I write the above I get compiler errors, these are the latest:
bin/Base.h: In instantiation of ‘Base<T>::Base(int, int, int, T&&) [with T = int]’:
bin/Base.h:33:82: required from here
bin/Base.h:12:96: error: no matching function for call to ‘forward(int&)’
/usr/include/c++/4.7/bits/move.h:77:5: note: template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_Tp>::type&)
/usr/include/c++/4.7/bits/move.h:77:5: note: template argument deduction/substitution
What am I doing wrong here?
Also, should I do std::move(data)
when data
in an int
or std::forward
?
Upvotes: 0
Views: 1263
Reputation: 154035
If you want to perfectly forward an argument, you'll either need to provide the corresponding three overloads or make the argument a template argument. In either case, when you want to use std::forward()
you'll need to specify the first template argument as it is not deduced. Most likely, you'd use something like this:
template <typename T>
class Base {
public:
template <typename A>
Base(A&& data): data(std::forward<A>(data)) {}
};
Trying to std::move(data)
when data
is a std::vector<uint16_t> const&
won't move the vector nor will it make the object look like a non-const
rvalue: if you want to make the vector movable, you'll need to pass it as non-const
reference, an rvalue, or a value. You may also want to deduce the type or overload on std::vector<uint16_t>&&
and std::vector<uint16_t>&
. For both of these overloads using std::move()
does the trick. If you deduce the type, you'll use std::forward<A>(data)
again. In case the deduced type looks to scare, you can constrain it using std::enable_if<...>
using something like this:
template <typename A>
DerivedB(A&& arg,
typename std::enable_if<std::is_same<typename std::decay<A>::value,
std::vector<uint16_t>>::value>::type* = 0):
Base(std::forward<A>(arg)) {
}
Upvotes: 1