变体构造器模板的专业化类模板 [英] Specialization of variadic constructor template of class template

查看:84
本文介绍了变体构造器模板的专业化类模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是一个带有可变构造函数的类,它的专业是复制和从临时类移动。

  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 推导为 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.

Live demo

这篇关于变体构造器模板的专业化类模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆