你被贪婪的完美转发构造函数咬住了。
wrapper<int> w2(w1);
在上面的行中,与复制构造函数相比,完善转发构造函数是更好的匹配,因为Args
推导为wrapper<int>&
.
一个快速修复解决方案是将上面的行更改为
wrapper<int> w2(static_cast<wrapper<int> const&>(w1));
这正确地调用了复制构造函数,但除了不必要的冗长之外,并没有解决基本问题。
为了解决原来的问题,你需要在以下情况下有条件地禁用完美转发构造函数:Args
是相同的wrapper<Obj>
.
Here's https://web.archive.org/web/20141205121901/http://flamingdangerzone.com:80/cxx11/2012/06/05/is_related.html一篇优秀的博客文章描述了该问题以及如何解决它。总而言之,您需要将完美的转发构造函数定义更改为
template <typename... Args,
DisableIf<is_related<wrapper<Obj>, Args...>::value>...>
wrapper(Args&&... args):
_Data(std::forward<Args>(args)...) {}
where is_related
定义为
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
是别名模板std::remove_cv
and std::remove_reference
分别。
现场演示 http://coliru.stacked-crooked.com/a/a9b7a1e17e580291