How can I do work with the type of templates with links?

I have a template function, func :

 template<typename T> void func(T p) { f(p); } 

And the set of functions f :

 f(SomeType&); f(int); ... 

If I create an instance of the template function, func , using the link as an argument to the p function, without explicitly specifying the template parameter T , the output type will not be the reference type p , but rather the type p is a reference to, for example:

 SomeType s; SomeType& ref_to_s = s; func(ref_to_s); // Type deduction results in: func<SomeType>(ref_to_s) func<SomeType&>(ref_to_s); // Need to explicitly specify type to work with reference 

So my questions are:

  • Why the compiler could not deduce the reference type SomeType& in the above situation?
  • Is there a way to define the func template function so that type inference works with the reference type without explicit specifying the template parameter T ?

To be clear, I need something to work with both (see f functions above):

 func(ref_to_s); // Calls func<SomeType&>(ref_to_s) func(1); // Calls func<int>(1) 
+7
c ++ c ++ 11 templates c ++ 14
source share
3 answers

The answer to the first part is that initializing an object from a value and linking a link to a value are considered equally good (both are “exact matches” when resolving overloads), so the parameter reference is not displayed. Rather, you must specify it exactly. For a corresponding example, consider a hypothetical construction

 T x = f(); 

where T is (throughout this thought experiment) what you must infer. What should be x be - an object or a link? What will it depend on? The expression on the right matters, of course, and the type of this value is always the type of the object. How do you decide? You can request a category of expression values, but this is too subtle. So instead, you should say what you want:

 T x = f(); // x is an object T & r = f(); // r is a reference 

In C ++, this mechanism is really available if you replace T with auto . The same rules apply to subtracting template arguments for function templates.

Now about how to solve your problem. The usual idiom is to make the function template always take a reference, and then redirect the argument to an internal call:

 template <typename T> void func(T && t) { f(std::forward<T>(t)); }; 

Now the func parameter is always a reference in any specialization (but thanks to a strange rule called "collapsing reference", it can be either an lvalue or an rvalue), and this value is sent from the same group of value categories to f , and this overload resolution on f allows you to choose lvalue-reference overloads when the original argument to func was an lvalue.

+9
source share

Use Forward Link:

 template<typename T> void func(T && p) //notice && { f(std::forward<T>(p)); //notice std::forward } 

Now try to find the forwarding link (or the universal link, as mentioned earlier), as well as std::forward on this site, to learn more about them.

+7
source share

Given the following example:

 template<typename T> void f(T value, T& ref) {// fake swapping T temp = ref; ref = value; value = temp; } 

When the compiler tries to deduce type T, it’s only reasonable to remove the possible references from “value” and “ref” first

 int i = 1; int j = 2; f(i, j); //value of j becomes 1. //up to here, value of i is still 1 

Otherwise, everything will be rather strange. If T is otherwise displayed in T &, then the type f (i, j) will then be equivalent to f (int &, int & &). Assuming T & and collapses to T &, then it becomes f (int &, int &). This is completely against the intention of the programmer.

0
source share

All Articles