c++ - 类模板的可变参数构造函数模板的特化

标签 c++ c++11 templates variadic-templates

这是一个具有可变参数构造函数的类,它专门用于从临时对象复制和移动。

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>>;

RemoveCvRemoveReferencestd::remove_cv 的别名模板和 std::remove_reference分别。

Live demo

关于c++ - 类模板的可变参数构造函数模板的特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21391184/

相关文章:

c++ - 使用 C++ 库根据键对对象进行排序的最快方法是什么?

c++ - 基于范围的 for 循环从 1 而不是 0 开始?

c++ - 返回不同的数据类型而不明确指定数据类型

c++ - 为什么 C++ const 引用可以折叠成非常量引用

c++ - 包含仅 move 类型的类的构造函数应该通过引用还是通过右值引用接收仅 move 类型?

c++ - 在 VS2005 上使用 "--layout=system"时 boost 链接错误

c++ - 为什么我的 OpenGL 自定义着色器给我这个错误?

c++ - 为什么 std::u16string 比 char16_t 数组慢?

c++ - std::tuple 中的空类型

php - mysql/php - 在数据库中存储 html 模板