# Question on Function template

Hi
I want to see whether there is a way to make this program work without much complication. I read from Ivor book that you can work with two different type of variables for example mixing int x = 1 and double y = 2.5 and use template to swap them using declaration <double> in the program as shown in the line 13. But I run into problem, this method will not work if I use reference for arguments as show in line 4. It will give me an error.

Obviously, it I remove the '&' to pass by value, it would not give an error, BUT it won't work as it's shallow copy. The values pass into the swapVars() and actually does the swapping when I step through it. But I cannot copy back into x and y as var1 and var2 are destroy once they go out of scope. Is there any way easy to make this work with reference as argument?
C++:
#include <iostream>
using namespace std;
template <class T>
void swapVars(T &var1, T &var2)
{    T temp;
temp = var1;
var1 = var2;
var2 = temp;
}
int main()
{    int  x = 1;
double y = 2.5;
swapVars<double>(x, y);
cout << " Swap int x=1 with double y=2.5 = " << x << ", " << y << "\n\n";
return 0;
}
The error message is:

Below is the program passing by value, I stepped through and you can see the local window shows the two numbers are successfully swapped. But like I said, this is shallow copy, I cannot pass the value back to x and y. This might be useful when dealing with mix type numbers if I can make it work.

thanks

Filip Larsen
Gold Member
It should be possible to make a "swap-values-with-explicit-cast" using two template arguments. Something along the following:
C++:
template <class T1, class T2>
void valueSwap(T1 &v1, T2 & v2) {
T1 temp = v1;
v1 = static_cast<T1>(v2);
v2 = static_cast<T2>(v1);
}

yungman
Staff Emeritus
ints are not doubles.
pointers to ints are not pointers to doubles.

Mark44
Mentor
yungman said:
C++:
void swapVars(T &var1, T &var2)
{    T temp;
temp = var1;
var1 = var2;
var2 = temp;
}
As already mentioned, to swap two variables of different types, you can't have them both be the same type. This is what the parameter list is saying, with both parameters being the parametrized type T.
More to the point, this is not what template functions are for. As a much simpler example, you could write a template function that could add two ints or two floats, or two complex values, or whatever, and the compiler would generate instances of each type of function based on how the templates are instantiated.

Last edited:
Mark44
Mentor
I posted an example program that used template functions -- https://www.physicsforums.com/threads/why-using-polymophism-here.998431/post-6446631

You didn't comment on it, so I don't know if you saw it -- here it is again now that you're working with template functions.
C++:
// TemplateFn.cpp - Example of templatized functions
#include <ccomplex>
#include <iostream>
using std::complex;
using std::cout;
using std::endl;

template <class T>                // Template function for sum
T sum(T a, T b) { return a + b; }            // Note that both template parameters are the same type

template <class T>                  // Template function for product
T prod(T a, T b) { return a * b; }           // Both template parameters are the same type

int main()
{
// Create three instances of each template function
int a = 3, b = 5;
// Call sum() and prod() with int arguments
int intRet1 = sum<int>(a, b);
int intRet2 = prod<int>(a, b);
cout << "Integer sum: " << intRet1 << " product: " << intRet2 << endl;

double c = 2.5, d = 3.8;
// Call sum() and prod() with double arguments
double dblRet1 = sum<double>(c, d);
double dblRet2 = prod<double>(c, d);
cout << "Double sum: " << dblRet1 << " product: " << dblRet2 << endl;

complex<double> e = { 2.5, 3.0 }, f = { 6.0, -2.0 };
// Call sum() and prod() with complex arguments
complex<double> cmplxRet1 = sum<complex<double>>(e, f);
complex<double> cmplxRet2 = prod<complex<double>>(e, f);
cout << "Complex sum: " << cmplxRet1 << " product: " << cmplxRet2 << endl;
}

Output:
Code:
Integer sum: 8 product: 15
Double sum: 6.3 product: 9.5
Complex sum: (8.5,1) product: (21,13)
In the last line, the sum is 8.5 + 1i, and the product is 21 + 13i, the usual notation for complex numbers that mathematicians use.

Last edited:
yungman
Thanks all, this explicit template arguments is from Ivor book, I just thought if I can do it without much fuzz, then maybe it's useful. I am not going to pursue this anymore.

Hi Mark, I don't remember I saw your example, I have to look into your example.

Thanks

I posted an example program that used template functions -- https://www.physicsforums.com/threads/why-using-polymophism-here.998431/post-6446631

You didn't comment on it, so I don't know if you saw it -- here it is again now that you're working with template functions.
C++:
// TemplateFn.cpp - Example of templatized functions
#include <ccomplex>
#include <iostream>
using std::complex;
using std::cout;
using std::endl;

template <class T>                // Template function for sum
T sum(T a, T b) { return a + b; }            // Note that both template parameters are the same type

template <class T>                  // Template function for product
T prod(T a, T b) { return a * b; }           // Both template parameters are the same type

int main()
{
// Create three instances of each template function
int a = 3, b = 5;
// Call sum() and prod() with int arguments
int intRet1 = sum<int>(a, b);
int intRet2 = prod<int>(a, b);
cout << "Integer sum: " << intRet1 << " product: " << intRet2 << endl;

double c = 2.5, d = 3.8;
// Call sum() and prod() with double arguments
double dblRet1 = sum<double>(c, d);
double dblRet2 = prod<double>(c, d);
cout << "Double sum: " << dblRet1 << " product: " << dblRet2 << endl;

complex<double> e = { 2.5, 3.0 }, f = { 6.0, -2.0 };
// Call sum() and prod() with complex arguments
complex<double> cmplxRet1 = sum<complex<double>>(e, f);
complex<double> cmplxRet2 = prod<complex<double>>(e, f);
cout << "Complex sum: " << cmplxRet1 << " product: " << cmplxRet2 << endl;
}

Output:
Code:
Integer sum: 8 product: 15
Double sum: 6.3 product: 9.5
Complex sum: (8.5,1) product: (21,13)
In the last line, the sum is 8.5 + 1i, and the product is 21 + 13i, the usual notation for complex numbers that mathematicians use.
Hi Mark

I did not see this, I just starting to learn templates. Looks like you are keeping things simple, not trying are the twist and turn. That's what I learned in the Gaddis book.

Since I have the Ivor and Lippman book, I read more on function. Ivor has a lot more twist and turns. This is one example in the book.

Maybe I should not study too much pass what you show in your example.

Thanks

Mark44
Mentor
Without seeing how the larger() template function is defined, I can't comment on the text from Ivor or your notes.

It looks like larger() is defined something like this:
C++:
template <class T>
T larger(int smInt, T val)
{ ... }
In the above, only the second parameter is templatized, but again I haven't seen the code, and I don't know how the body of the template function is implemented.

Some examples of how this template function might be instantiated:
C++:
int smInt = 5;
int iResult = larger<int>(smInt, 14);         // Should return 5
double dResult = larger<double>(smInt, 3.0)  // Should return 3.0

Last edited:
yungman
Mark44
Mentor
Looks like you are keeping things simple, not trying are the twist and turn.
Most of my examples are pretty simple, or at least not trying to do much more than give some explanation of the concept I'm trying to get across. When you're trying to learn something new, the KISS principle is important.

yungman
Without seeing how the larger() template function is defined, I can't comment on the text from Ivor or your notes.

It looks like larger() is defined something like this:
C++:
template <class T>
T larger(int smInt, T val)
{ ... }
In the above, only the second parameter is templatized, but again I haven't seen the code, and I don't know how the body of the template function is implemented.

Some examples of how this template function might be instantiated:
C++:
int smInt = 5;
int iResult = larger<int>(smInt, 14);         // Should return 5
double dResult = larger<double>(smInt, 3.0)  // Should return 3.0
Yes, I should have attached the original program. Here it is:

It works if I use function with return as it won't go out of scope until it return to the main program. It just won't work if you have multiple values to get back to main().
This program works if I only need to return one value:
C++:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
template<class T>  T larger(T a, T b)
{if (a > b) return a;else if (b > a)return b; return a;}
//{    return a > b ? a : b;}
int main()
{    double x=2.5, y=4.5; cout<<" larger of x and y is: "<<larger(x, y)<<endl;
int big=4,small=1;cout<<" larger of big and small is: "<<larger(big, small)<<endl;
string a="Alan",b="Alan";cout<<" larger of string a and b is: "<<larger(a, b)<<endl;
cout<<" larger of big and y is: "<<larger<double>(big, y) << endl;// This one works using return from larger.
return 0;
}

Thanks

jbunniii
Homework Helper
Gold Member
template<class T> T larger(T a, T b) accepts its arguments by value. A call such as
C++:
int a = 1;
double d = 2.0;
double maxVal = larger<double>(a, d);
is permissible because the int argument a is implicitly convertible to a double.

Your earlier example template <class T> void swapVars(T &var1, T &var2) will not work the same way because it accepts its arguments by reference. A reference to an int is not implicitly convertible to a reference to a double. That's why this fails to compile:
C++:
int a = 1;
double d = 2.0;
swapVars<double>(a, d);
This limitation is not specific to template functions. The following will also not compile:
C++:
double swapVars(double& a, double& b)
{
double temp = a;
a = b;
b = temp;
}
If you want a template function to be able to accept arguments of two different types, the way to do it is
C++:
template<class S, class T>
void swapVars(S& a, T& b)
{
S temp = a;
a = b;
b = temp;
}
This will allow you to make the function call with two different types. However, if the types are incompatible for assignment, you'll still get a compilation error:
C++:
int a = 1;
double d = 2.0;
swapVars<double>(a, d);
will not work because the template function will be expanded as
C++:
void swapVars(int& a, double& b)
{
int temp = a;
a = b;
b = temp;
}
and the line int temp = a; is disallowed because you're assigning a double to an int. The compiler is protecting you from making a mistake! The underlying problem is that you can't swap a double and an int, because a double can contain values that cannot be stored in an int, such as 1.5, which has a fractional part, or 281474976710656, which is larger than 32 bits but less than the 51 mantissa bits used by double.

Last edited:
yungman
Mark44
Mentor
Snipped from your example in post #10:
C++:
double x=2.5, y=4.5; cout<<" larger of x and y is: "<<larger(x, y)<<endl;
int big=4,small=1;cout<<" larger of big and small is: "<<larger(big, small)<<endl;
string a="Alan",b="Alan";cout<<" larger of string a and b is: "<<larger(a, b)<<endl;
I haven't attempted to compile your code, but you are not calling the template function larger() correctly in these three lines.
The first line should have this call: larger<double>(x, y)
The second should be like this: larger<int>(big, small)
The third should be like this: larger<string>(a, b)

Your fourth line, not shown above, is written correctly, but I don't understand what your comment is trying to convey: "This one works using return from larger."
It works if I use function with return as it won't go out of scope until it return to the main program. It just won't work if you have multiple values to get back to main().
I don't understand what you are saying here about "function with return" and not going out of scope. Again, you are not calling your template function correctly in the first three examples. The code I posted earlier should give you an idea of how to call a template function; i.e., with <type> right after the function name but before the arguments in parentheses.
This program works if I only need to return one value:
A function returns only one value, so I don't get your point here, either.

yungman
Staff Emeritus
It should be possible to make a "swap-values-with-explicit-cast" using two template arguments. Something along the following:

Um, well, maybe.

(BTW, there's a bug in your code.
Code:
v2 = static_cast<T2>(v1)
needs to be
Code:
v2 = static_cast<T2>(temp)
)

The problem is that if you try and swap 1 and 2.6. You will get 2 and 1.0. The 2.6 gets truncated when it is shoehorned into an int. Or if you swap 1 with 1e12. You'll get a mess.

It's not the fault of your code. It's a perfectly good implementation of what is surely a logic error in the code. "Swap a variable that's a double with one that's an int without any checking that it in fact fits" is probably not what the programmer intends.

Filip Larsen
Snipped from your example in post #10:
C++:
double x=2.5, y=4.5; cout<<" larger of x and y is: "<<larger(x, y)<<endl;
int big=4,small=1;cout<<" larger of big and small is: "<<larger(big, small)<<endl;
string a="Alan",b="Alan";cout<<" larger of string a and b is: "<<larger(a, b)<<endl;
I haven't attempted to compile your code, but you are not calling the template function larger() correctly in these three lines.
The first line should have this call: larger<double>(x, y)
The second should be like this: larger<int>(big, small)
The third should be like this: larger<string>(a, b)

Your fourth line, not shown above, is written correctly, but I don't understand what your comment is trying to convey: "This one works using return from larger."
I don't understand what you are saying here about "function with return" and not going out of scope. Again, you are not calling your template function correctly in the first three examples. The code I posted earlier should give you an idea of how to call a template function; i.e., with <type> right after the function name but before the arguments in parentheses.
A function returns only one value, so I don't get your point here, either.
Thanks Mark

Sorry I did not come back for 2 days, grand daughter is staying with us for a week, got really busy.

Regarding to not having larger<double>() or larger<in>() is because that's how the book said. Take a look at the program Ex9.01 that I copied from the book. This is how template supposed to work. You don't have to specify the type, the template will take care of it.

Thanks

template<class T> T larger(T a, T b) accepts its arguments by value. A call such as
C++:
int a = 1;
double d = 2.0;
double maxVal = larger<double>(a, d);
is permissible because the int argument a is implicitly convertible to a double.

Your earlier example template <class T> void swapVars(T &var1, T &var2) will not work the same way because it accepts its arguments by reference. A reference to an int is not implicitly convertible to a reference to a double. That's why this fails to compile:
C++:
int a = 1;
double d = 2.0;
swapVars<double>(a, d);
This limitation is not specific to template functions. The following will also not compile:
C++:
double swapVars(double& a, double& b)
{
double temp = a;
a = b;
b = temp;
}
If you want a template function to be able to accept arguments of two different types, the way to do it is
C++:
template<class S, class T>
void swapVars(S& a, T& b)
{
S temp = a;
a = b;
b = temp;
}
This will allow you to make the function call with two different types. However, if the types are incompatible for assignment, you'll still get a compilation error:
C++:
int a = 1;
double d = 2.0;
swapVars<double>(a, d);
will not work because the template function will be expanded as
C++:
void swapVars(int& a, double& b)
{
int temp = a;
a = b;
b = temp;
}
and the line int temp = a; is disallowed because you're assigning a double to an int. The compiler is protecting you from making a mistake! The underlying problem is that you can't swap a double and an int, because a double can contain values that cannot be stored in an int, such as 1.5, which has a fractional part, or 281474976710656, which is larger than 32 bits but less than the 51 mantissa bits used by double.
Thanks for the reply. I understand this, my question is really trying to mix 2 types with one Template defined type given by the Ivor book, the first example is in post 10 and the method of mixing two types is given in post 7. You can see the example in post 7 works. I am trying to use variables rather given a number like in the example in post 7 and I cannot make it work. Maybe there is no way to do it.

Thanks

Mark44
Mentor
Copied from post #12:
I haven't attempted to compile your code, but you are not calling the template function larger() correctly in these three lines.
The first line should have this call: larger<double>(x, y)
The second should be like this: larger<int>(big, small)
The third should be like this: larger<string>(a, b)
What I wrote above uses explicitly specified template arguments. I didn't realize that the template arguments aren't required. If you don't include them, the VS docs call this "deduced template arguments." This doc page shows an example with both types of function template instantiation - Function Template Instantiation | Microsoft Docs
Regarding to not having larger<double>() or larger<in>() is because that's how the book said. Take a look at the program Ex9.01 that I copied from the book. This is how template supposed to work. You don't have to specify the type, the template will take care of it.
I stand corrected.

yungman
Hi

I really have not work on this very much, been really busy. I have a question when I play with templates, this is not a working nor complete program, but I have a more important question:
C++:
#include <iostream>
using namespace std;
template <class T>
T var1;
template<class T>
T var2;
template<class T>
T swapVars(&var1,&var2) { T temp = a; a = b; b = temp;}
int main()
{
int a = 1; double d = 2.0;
cout << swapVars(a, d) << endl;

}

My question is why VS flags error if I don't put in line 5 and 7? It's like template<class T> only good for the very next declaration. That you have to write template<class T> again. In my program, I have to write 3 times.

I thought it's like defining a certain type, you declare once and you can use it for the rest of the program.

I am not even sure there is only one type T or have 3 different T types like this. I am seriously missing something here, none of the 3 books even talk about this.

Thanks

Staff Emeritus
My question is why VS flags error if I don't put in line 5 and 7?

Because you have to declare the type of a variable before you use it. See Chapter 2 of Gaddis. If you don't have that, you just have "T var1", and how is the compiler supposed to know what T is?

This is a direct consequence of your stubborn refusal to follow the advice of what to put on a line, although here you are splitting something that should be one line and not joining some things that should be in more than one.

Furthermore, this code will never work. This whole thread explains why.

Because you have to declare the type of a variable before you use it. See Chapter 2 of Gaddis. If you don't have that, you just have "T var1", and how is the compiler supposed to know what T is?

This is a direct consequence of your stubborn refusal to follow the advice of what to put on a line, although here you are splitting something that should be one line and not joining some things that should be in more than one.

Furthermore, this code will never work. This whole thread explains why.
Did you read my question? The question is WHY I have to declare 3 times template<class T>. NOT why I have to declare template<class T> once at the beginning. Read the question again.

I KNOW the code is not working, I said so already. I just want to know why I have to keep declaring the template on every single variable and function return. Look at the question.

Staff Emeritus

jbunniii
Homework Helper
Gold Member
C++:
template<class T>
T swapVars(&var1,&var2) { T temp = a; a = b; b = temp;}
Should be:
C++:
template<class T>
void swapVars(T& var1, T& var2) { T temp = var1; var1 = var2; var2 = temp;}
1. You omitted the types of the arguments.
2. Your arguments are var1 and var2, but the function implementation uses (undefined) a and b.
3. If you want the return type to be non-void, you have to actually return something!

Hi guys

There is a lot of confusion in this thread. I want to sum it up, please bear with me. My original question is on EXPLICIT argument that I can use only one template to work on two different types of variables. I want to gather everything into this thread, it's going to be long. It all started out with Ivor book program 9.1. Then it introduce the explict argument in the second page of the book shown below:

Here is book introducing explicit argument using program 9.1 above:

You can see by using <double> or <int>, it can force the program to work with two different types of variables with a single template declaration.

But I found the application is very limited. For function that return the variable, it will work as shown in the following program:
C++:
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
template<class T>  T larger(T a, T b)
{if (a > b) return a;else if (b > a)return b; return a;}
//{    return a > b ? a : b;}
int main()
{    double x=2.5, y=4.5; cout<<" larger of x and y is: "<<larger(x, y)<<endl;
int big=4,small=1;cout<<" larger of big and small is: "<<larger(big, small)<<endl;
string a="Alan",b="Alan";cout<<" larger of string a and b is: "<<larger(a, b)<<endl;
cout<<" larger of big and y is: "<<larger<double>(big, y) << endl;
return 0;
}
If you run the program, you can see line 12 will return the correct value even though the argument is passed by value. This is the printout:
larger of x and y is: 4.5
larger of big and small is: 4
larger of string a and b is: Alan
larger of big and y is: 4.5

BUT
by using function with return, I can only return a single variable. In the next program, I need to use both variables from the function. That's when I run into problem. The reason is the variables var1 and var2 are going out of scope and won't be copied back to x and y. This is the program.

I stepped through the program showing I got the correct values into var1, var2 and temp. I just cannot copy back to x and y.

So the next logical step is to pass by reference as shown in program below. Of cause it doesn't work as it is CLEAR that you cannot pass reference of a type int to a type double as reference. I understand this much already before people explain to me over and over:
C++:
template <class T>
void swapVars(T &var1, T &var2)
{    T temp;
temp = var1;
var1 = var2;
var2 = temp;
}
int main()
{    int  x = 1;
double y = 2.5;
swapVars<double>(x, y);
cout << " Swap int x=1 with double y=2.5 = " << x << ", " << y << "\n\n";
return 0;
}

Now, this is really my question from the very first post. Is there any easy way to make it work to return back two variables like it the Swap program.

Filip Larsen already suggested using two templates: template <class T1, class T2>, but I really don't want to be this complicate. I want to see whether there is something simpler.

So my latest idea is to put var1 and var2 as global so I DO NOT have to use passing argument by reference, I just pass by value. BUT being global variables, it will NOT go out of scope. Now I encountered a new problem. I need to define T var1, T var2 and void swapVars( T var1, Tvar2). But it cannot be done. you can see the red lines lighted up the program:

I think I am seriously missing something in template. It is definitely not the same as other ADT that you can just declare ones like template<class T> and use T to declare other variables. I went through all 3 books, none talked about this. How do I use template? it's not the same as declaring ADT at all.

I am willing to accept that there is no easy way to do swapVars() other than using what Filip Larsen suggested. I just want to know what am I missing about function templates.

Thanks

Mark44
Mentor
Now, this is really my question from the very first post. Is there any easy way to make it work to return back two variables like it the Swap program.
Yes.
C++:
#include <iostream>
template <class T>
void swapVars(T &var1, T &var2)
{
T temp = var1;
var1 = var2;
var2 = temp;
}

int main()
{
double x = 1.0, y = 2.5;
swapVars<double>(x, y);
std::cout << x << ", " << y << std::endl;
}
The code for swapVars() is almost identical to yours. The main difference is in main(), in how swapVars() is called (and instantiated).
Filip Larsen already suggested using two templates: template <class T1, class T2>, but I really don't want to be this complicate. I want to see whether there is something simpler.
See above.
So my latest idea is to put var1 and var2 as global
I think I am seriously missing something in template.
Yes.
In your template function, both formal parameters are declared to be of the same type -- T -- so both actual parameters, the ones used when you call swapVars(), should also be the same type. The clue should be in the error that VS produces:
C2664 - 'void swapVars<double>(T&, T&)': cannot convert argument 1 from 'int' to 'T&'

If you're going to swap two things, it doesn't make a lot of sense if the two things aren't the same type, so I don't know why you're trying to make a function template that would swap, say, an int with a double. For one thing, they are different sizes, with an int being 4 bytes and a double being 8 bytes.

yungman
Thanks Mark, I guess it's not a good idea to use explicit arguments to mix two data types into a single template like the Ivor book. I just want to move on.

I don't get your second part. I want to clarify with these two example what I am trying to ask.

This is an example using ADT type with class. You can see once I declare class Test, I can create object T and R.
C++:
#include <iostream>
using namespace std;
class Test
{
public:    int a;
};

int main()
{
Test T, R;// I can declare T and R as object of class Test
return 0;
}

But with template, I cannot do that. Why? See example below:
C++:
#include <iostream>
using namespace std;
template <class T>
T var1; T var2;//I cannot declare var1 and var2 as type T.
void swapVars( var1,  var2)//error again.
{    T temp;
temp = var1;
var1 = var2;
var2 = temp;
}
int main()
{    int  x = 1;
double y = 2.5;
swapVars<double>(x, y);
cout << " Swap int x=1 with double y=2.5 = " << x << ", " << y << "\n\n";
return 0;
}

Why are the two cases different?

Thanks

Mark44
Mentor
Thanks Mark, I guess it's not a good idea to use explicit arguments to mix two data types into a single template like the Ivor book. I just want to move on.
It depends on what you want to do with the template function. If it makes sense to do something with two different types of objects, then you should be able to write a template function to do that. But it doesn't make sense to try to swap two objects of different types. What happens if the types you want to swap are a float and a string; a char and a double; a struct of some kind and a short? Trying to swap an int and a double falls into the same category. I explained why this is a fruitless pursuit in a fair amount of detail in post #23. Please reread what I wrote.
But with template, I cannot do that. Why? See example below:
Again, see what I wrote in post #23, including the compiler error that you get from VS.
Your example is essentially identical to the example several posts back. Why are you still trying to get something to work that is pretty much doomed to failure?
Why are the two cases different?
Please reread what I wrote in post #23. If you have specific questions on what I wrote, ask them, but please stop asking why what you're trying to do doesn't work when it has been explained to you multiple times.