I want to implement a perfect forwarding constructor in my "myArgs class",
which should only get involved for specializations of myClassBase<>
.
Roughly speaking: call this constructor for each variation of myClassBase<>
But it won't compile: '<function-style-cast>' : cannot convert from 'myClass' to 'myArgs'.
I think it's because the compiler can't deduce from Args&&
to myClassBase<T, D>
.
See this (very basic) example:
template <class T, class D>
class myClassBase
{
private:
T data;
D data2;
};
typedef myClassBase<char, int> myClass;
class myArgs
{
public:
myClass m_data;
template <class T, class D>
myArgs(myClassBase<T, D>&& rhs) :
m_data(std::forward< myClassBase<T, D> >(rhs))
{
}
};
template <class... Args>
void var_args(Args&&... args)
{
myArgs( std::forward<Args>(args)... );
}
Test the stuff:
myClass x;
var_args(x);
If i change the var_args function parameter from void var_args(Args&&... args)
to void var_args(Args... args)
it works.
Btw. in my real code myClass of course supports move semantics.
Thanks in advance. Christian.
template <class T, class D>
myArgs(myClassBase<T, D>&& rhs) :
m_data(std::forward< myClassBase<T, D> >(rhs))
{
}
rhs
there is an rvalue reference, not a forwarding reference. A forwarding reference in a function parameter be of the form T&&
where T
is some deduced template parameter. You can fix this by having T
deduced rather than specifying myClassBase
.
template <class T>
myArgs(T&& rhs) :
m_data(std::forward<T>(rhs))
{
}
If you want this function to only be valid if T
is a myClassBase
, you can write a trait to check it:
template <typename T>
struct isMyClassBaseImpl : std::false_type{};
template <typename T, typename D>
struct isMyClassBaseImpl<myClassBase<T,D>> : std::true_type{};
template <typename T>
using isMyClassBase = isMyClassBaseImpl<std::decay_t<T>>;
Then you can SFINAE it out:
template <class T, std::enable_if_t<isMyClassBase<T>::value>* = nullptr>
myArgs(T&& rhs) :
m_data(std::forward<T>(rhs))
{
}