变体构造器模板的专业化类模板 [英] Specialization of variadic constructor template of class template
问题描述
这里是一个带有可变构造函数的类,它的专业是复制和从临时类移动。
template< class Obj>
类包装器{受保护的
:
Obj _Data;
public:
wrapper(const wrapper< Obj> w):_Data(w._Data){}
wrapper(wrapper< Obj>& & w):
_Data(std :: forward< Obj>(w._Data)){}
template< class ... Args>
wrapper(Args&&... args):
_Data(std :: forward< Args>(args)...){}
内联对象operator()(){return _Data; }
virtual〜wrapper(){}
};
当我使用像这样的专业之一
wrapper< int> w1(9);
wrapper< int> w2(w1);
我遇到了错误: w1 $ c $的类型c>推导为
int
。
VS2012的输出:
错误C2440:正在初始化:无法从 win :: util :: wrapper< int>转换为 int
如何解决此问题?
您
wrapper< int> w2(w1);
在上面的行中,与复制构造函数相比,完善的转发构造函数更合适,因为 Args
推导为 wrapper< int>&
。
一种快速解决方案是将上面的行更改为
wrapper< int> w2(static_cast< wrapper< int> const&>(w1));
这可以正确地调用复制构造函数,但是除了不必要的冗长之外,它不能解决基本问题。
要解决原始问题,您需要在 Args
与 wrapper< Obj>
。
这里是一篇出色的博客文章,描述了该问题以及如何解决。总之,您需要将完美的转发构造函数定义更改为
template< typename ... Args,
DisableIf< is_related< wrapper< Obj> ;, Args ...> :: value> ...>
wrapper(Args&&...; args):
_Data(std :: forward< Args>(args)...){}
其中是相关的
定义为
template< typename T,typename ... U>
struct is_related:std :: false_type {};
模板< typename T,typename U>
struct is_related< T,U> :std :: is_same< Bare< T> ;、 Bare< U> {};
和 Bare
是
模板< typename T>
使用Bare = RemoveCv< RemoveReference< T> ;;
RemoveCv
和 RemoveReference
分别是 std :: remove_cv
和 std :: remove_reference
的别名模板。 / p>
Here's a class with variadic constructor and it's specializations for copy and move from a temporary.
template<class Obj>
class wrapper {
protected:
Obj _Data;
public:
wrapper(const wrapper<Obj>& w): _Data(w._Data) {}
wrapper(wrapper<Obj>&& w):
_Data(std::forward<Obj>(w._Data)) {}
template<class ...Args>
wrapper(Args&&... args):
_Data(std::forward<Args>(args)...) {}
inline Obj& operator()() { return _Data; }
virtual ~wrapper() {}
};
When I use one of specializations like this
wrapper<int> w1(9);
wrapper<int> w2(w1);
I'm getting the error: type of w1
is deduced as int
.
Output from VS2012:
error C2440: 'initializing' : cannot convert from 'win::util::wrapper<int>' to 'int'
How to solve this problem?
You're getting bitten by the greedy perfect forwarding constructor.
wrapper<int> w2(w1);
In the line above, the perfecting forwarding constructor is a better match as compared to the copy constructor, because Args
is deduced as wrapper<int>&
.
A quick fix solution is to change the line above to
wrapper<int> w2(static_cast<wrapper<int> const&>(w1));
this correctly calls the copy constructor but, besides being unnecessarily verbose, doesn't solve the basic problem.
To solve the original problem, you need to conditionally disable the perfect forwarding constructor when Args
is the same as wrapper<Obj>
.
Here's an excellent blog post describing the problem, and how to solve it. To summarize, you need to change the perfect forwarding constructor definition to
template <typename... Args,
DisableIf<is_related<wrapper<Obj>, Args...>::value>...>
wrapper(Args&&... args):
_Data(std::forward<Args>(args)...) {}
where is_related
is defined as
template <typename T, typename... U>
struct is_related : std::false_type {};
template <typename T, typename U>
struct is_related<T, U> : std::is_same<Bare<T>, Bare<U>> {};
and Bare
is
template <typename T>
using Bare = RemoveCv<RemoveReference<T>>;
RemoveCv
and RemoveReference
are alias templates for std::remove_cv
and std::remove_reference
respectively.
这篇关于变体构造器模板的专业化类模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!