C ++ 11:如何定义一个接受特定类型对象的通用引用的函数? [英] C++11 : How can I define a function that accept a universal reference of a specific type of object?

查看:93
本文介绍了C ++ 11:如何定义一个接受特定类型对象的通用引用的函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:
我正在用C ++ 11开发一个程序。我想编写一个同时接受右值引用和左值引用的函数。 (即通用引用)。

Problem: I am developing a program with C++11. I want to write a function that accept both rvalue reference and lvalue reference. (i.e. universal reference).

以下函数接受通用引用参数:

The following function accept a universal reference parameter:

template<class T> void function(T&& t){/*SNIP*/}

但是,它接受所有参数类型。它破坏了函数的类型安全性。如果我希望它接受特定类型的参数,该怎么办?

However, it accepts all type of parameter. It ruins the type safety of the function. What should I do if I want it to accept a specific type of parameter?

这是我可以想到的解决方案:

Here is a solution that I can think of:

void function(Class& t){/*SNIP*/}
void function(Class&& t){ function(t); }

但是,它很难看。如果我想更改要接受的参数或更改函数名称,则必须同时更新两个版本的函数。

However, it's ugly. In case I want to change the parameter to be accepted, or changing the function name, I have to update both version of the function. It there a better equivalent than this?

编辑:问题已解决。你们都回答得很好。我对两个答案都投了+1,以表示赞赏。我将离开这个问题几天。投票最多的答案将被接受。

Problem solved. You both have answered quite well. I have voted +1 to both answers to show my appreciation. I am going to leave this question for a few days. The answer with the most votes will be accepted.

EDIT2:我最终得到以下代码:

I end up with the following code:

template < class T,
class=typename std::enable_if<std::is_same<Class, typename std::decay<T>::type>::value>::type //Dummy template parameter
>
void function(T&&){}

EDIT3:我已经写了一个宏为此的定义:

I have written a macro definition for this purpose:

#define uRefType(T, typeLimit) class T, class=typename std::enable_if<std::is_same<typename std::decay<T>::type, typeLimit>::value>::type

用法示例:

template< uRefType(T, Class) > void function(T&&){}


推荐答案

一个这样做的方法是使用 std :: enable_if 。这是 type_traits 标头提供的结构。以这样的方式定义: enable_if< A,B> :: type 是类型 B (如果是布尔值)条件 A 在编译时评估为true。否则为空。

One way of doing this is to use std::enable_if. That's a struct provided by the type_traits header. It is defined in such a way that enable_if<A,B>::type is the type B if the boolean condition A evaluates to true at compile time. Otherwise it is empty.

因此,如果您有功能模板

Hence, if you have a function template

template <typename T>
void fun(T &&)
{ /*...*/ }

,并且要确保仅在 T 是特定类型时才定义它,可以使用 enable_if< ...> ; :: type 构造而不是返回类型(此处为 void )。然后将布尔条件 A 定义为: T int ,类型 B 被定义为函数的原始返回类型(此处为 void )。

and you want to ensure it is only defined if T is a certain type, you can use the enable_if<...>::type construct instead of the return type (here, void). The boolean condition A is then defined as something like: T is int, and the type B is defined as the original return type of the function (here, void).

因此,如果我们想定义 fun 仅在 T int ,我们得到:

So, if we want fun to be defined only if T is int, we get this:

#include <type_traits>

template <typename T>
typename std::enable_if<std::is_same<int,typename std::decay<T>::type>::value,void>::type
fun(T &&)
{ }

int main()
{
  int    lvali = 3;
  double lvald = 3.3;

  fun(3);
  fun(lvali);

  // fun(3.3);      // this won't be accepted (not an int)
  // fun(lvald)     // this won't be accepted (not an int)

  return 0;
}

请注意,布尔条件的定义如下(省略 std :: 以获得更好的可读性):

Notice how the boolean condition is defined as follows (omitting std:: to for better readability):

is_same<int,typename decay<T>::type>::value

衰减语句用于确保无论 T int 还是 int& (还有其他一些特殊情况)。

The decay statement is used to ensure this works regardless of whether T is int or int & (and a few more special cases).

进一步说明:这种技巧是仅当有关函数的定义对于rvalue和lvalue相同时才真正有用。在很多情况下不是这种情况(因为右值案例将实现移动,左值案例将不会执行移动,或类似的操作)。

Further remarks: This sort of trick is only really useful if the definition of the function in question is the same for both rvalue and lvalue. In many cases that won't be the case (because the rvalue case will implement a move, the lvalue won't, or something similar).

典型情况是这两个定义实际上是相同的,即函数主体非常短,除了将参数转发给另一个(可能是重载的)函数调用外,什么也没有做:

A typical situation where both definitions are in fact the same is when the function body is very short and does nothing but forwarding the argument(s) to yet another (possibly overloaded) function call:

template <typename T>
void fun(T &&obj)
{ other_fun(std::forward<T>(obj)); }

在这种情况下,最好不要使用任何 enable_if 或其他技巧,因为 other_fun 的声明将确保最终仅接受某些类型。

In that case it is probably ok not to use any enable_if or other trick, because the declaration of other_fun will ensure that ultimately only certain types will be accepted.

这篇关于C ++ 11:如何定义一个接受特定类型对象的通用引用的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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