这是一个具有可变参数构造函数的类,它专门用于从临时对象复制和移动。
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() {}
};
当我使用这样的专业之一时
wrapper<int> w1(9);
wrapper<int> w2(w1);
我收到错误:w1
的类型被推断为 int
。
VS2012 的输出:
error C2440: 'initializing' : cannot convert from 'win::util::wrapper<int>' to 'int'
如何解决这个问题?
最佳答案
你被贪婪的完美转发构造函数咬伤了。
wrapper<int> w2(w1);
在上面的行中,与复制构造函数相比,完善的转发构造函数更匹配,因为 Args
推导为 wrapper<int>&
.
一个快速解决方案是将上面的行更改为
wrapper<int> w2(static_cast<wrapper<int> const&>(w1));
这正确地调用了复制构造函数,但除了不必要的冗长之外,并没有解决基本问题。
解决原问题需要在Args
时有条件地禁用完美转发构造函数与wrapper<Obj>
相同.
Here's一篇描述问题及其解决方法的优秀博客文章。总而言之,您需要将完美的转发构造函数定义更改为
template <typename... Args,
DisableIf<is_related<wrapper<Obj>, Args...>::value>...>
wrapper(Args&&... args):
_Data(std::forward<Args>(args)...) {}
哪里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>> {};
和Bare
是
template <typename T>
using Bare = RemoveCv<RemoveReference<T>>;
RemoveCv
和 RemoveReference
是 std::remove_cv
的别名模板和 std::remove_reference
分别。
关于c++ - 类模板的可变参数构造函数模板的特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21391184/