繁体   English   中英

C ++ 11:如何定义一个接受特定类型对象的通用引用的函数?

[英]C++11 : How can I define a function that accept a universal reference of a specific type of object?

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

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

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

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

这是我能想到的解决方案:

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

但是,这很丑。 如果我想更改要接受的参数或更改函数名称,则必须同时更新两个版本的函数。 还有比这更好的了吗?

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

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

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:为此我编写了一个宏定义:

#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标头提供的结构。 如果布尔条件A在编译时评估为true,则定义使enable_if<A,B>::type为类型B 否则为空。

因此,如果您有功能模板

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

并且要确保仅在T是某种类型的情况下定义它,可以使用enable_if<...>::type构造代替返回类型(此处为void )。 然后将布尔条件A定义为: Tint ,类型B定义为函数的原始返回类型(此处为void )。

因此,如果我们希望仅在Tint时才定义fun ,则可以得到以下信息:

#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::以获得更好的可读性):

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

使用decay语句可确保无论Tint还是int & (以及其他一些特殊情况),它都可以正常工作。


进一步说明:仅当所讨论的函数的定义对于rvalue和lvalue相同时,这种技巧才真正有用。 在许多情况下,情况并非如此(因为右值大小写将实现移动,左值大小写将不会执行移动,或类似的操作)。

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

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

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

std::enable_ifstd::is_same

template<class T, 
         class = typename std::enable_if<std::is_same<float, T>::value>::type>
void function(T&& t){/*SNIP*/}

(正如在jogojapan的答案,我忘了提,第一说明)使用std::decayT ,因为T&是不是同一类型的Tconst T是不一样的T`:

template<
  class T, 
  class = typename std::enable_if<
                       std::is_same<float,
                                    typename std::decay<T>::type>::value>::type>
void function(T&& t){/*SNIP*/}

参见http://ideone.com/ztkHsf上的演示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM