C ++ 11: How can I define a function that accepts a universal reference of a certain type of object?

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

The following function accepts a universal reference parameter:

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

However, it accepts all types of parameters. This destroys the type of security function. What if I want it to accept a certain type of parameter?

Here is a solution I can think of:

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

However, this is ugly. In case I want to change the accepted parameter or change the name of the function, I need to update both versions of the function. Is this the best equivalent?

EDIT: The problem is resolved. You both answered well. I voted +1 for both answers to express my appreciation. I am going to leave this question for a few days. A majority vote will be accepted.

EDIT2: I get 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: for this purpose I wrote a macro definition:

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

Usage example:

 template< uRefType(T, Class) > void function(T&&){} 
+4
source share
2 answers

One way to do this is to use std::enable_if . This is the structure provided by the type_traits header. It is defined in such a way that enable_if<A,B>::type is type B if the logical condition A evaluates to true at compile time. Otherwise, it is empty.

Therefore, if you have a function template

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

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

So, if we want fun be defined only if T is int , we get the following:

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

Note how a logical condition is defined as follows (excluding std:: for better readability):

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

The decay operator is used to provide this, regardless of whether T int or int & (and a few other special cases).


Further notes: This trick is really only useful if the definition of the function in question is the same for both rvalue and lvalue. In many cases this is not the case (because the rvalue case will implement the move, the lvalue will not, or something like that).

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

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

In this case, you probably should not use any enable_if or other trick, because declaring other_fun ensures that only certain types are ultimately accepted.

+4
source

Use std::enable_if with std::is_same :

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

And (as the answer from jogojapan I forgot to mention), use std::decay in T , as T& not the same type as T , and const T does not match 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*/} 

See the demo version of http://ideone.com/ztkHsf .

+1
source

All Articles