模板转发调用成员的方法

时间:2016-07-01 09:33:12

标签: c++ templates reference sfinae

请考虑以下事项:

template <typename type> class my_wrapper
{
  type _;

  template <typename... types, typename std :: enable_if <has_my_method_callable_with_the_following_types <type, types...> :: value> :: type * = nullptr> void my_method(types... items)
  {
    _.my_method(items...);
  }
};

正如您可以想象的那样,has_my_method_callable_with_the_following_types是某种SFINAE结构,它允许我确定type是否具有可以使用这些类型调用的方法。

您可以很容易地看到,上面的示例基本上将所有对my_method的调用转发到_。好。 几乎所有这些。如果我这样做会发生什么:

class my_type
{
  void my_method(int & x)
  {
    x++;
  }
};

my_wrapper <my_type> my_wrapped;

int x;
my_wrapped.my_method(x);

显然上述内容不起作用,因为x将通过副本传递给函数,而my_type :: my_method通过引用接受它。所以我想知道:有什么方法可以解决这个问题吗?我当然可以这样做:

template <typename... types, typename std :: enable_if <has_my_method_callable_with_the_following_types <type, types & ...> :: value> :: type * = nullptr> void my_method(types & ... items)
{
  _.my_method(items...);
}

然后对称地说,当我通过时,我会遇到问题,比如int文字,我不能通过引用来获取但是某些my_type :: my_method(int x)完全可以接受。

我该如何解决这个问题?我想将所有来电my_wrapper <type> :: my_method无缝转发到type :: my_method

盗贼要小心:我不能使用继承,所以请不要建议! :)

1 个答案:

答案 0 :(得分:2)

这是完全引入的完美转发和转发引用:

template <
  typename... types,
  typename std :: enable_if <has_my_method_callable_with_the_following_types <type, types...> :: value> :: type * = nullptr
> void my_method(types&&... items)
{
  _.my_method(std::forward<types>(items)...);
}

这是如何运作的:

该语言中有一条特殊规则,即当在T构造中推导出T&&时,用于演绎的参数是U类型的左值,那么{{ 1}}被推断为T而不是U&

净效应是当参数是转发引用(U推导出的T&&)时,它将是左值引用(如果参数是左值)或rvalue引用(如果参数是右值)。然后,T会根据需要将其强制转换为左值或右值。