Function Template: Solve Complications with Mixing Types for Variable Swapping

  • Thread starter yungman
  • Start date
  • Tags
    Function
In summary: Ret2 << endl;In summary, the problem is that you cannot copy the values x and y back into var1 and var2 because they are destroyed once they go out of scope. You could make a "swap-values-with-explicit-cast" using two template arguments. Something along the following:
  • #1
yungman
5,708
240
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:
Swap 2.jpg


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.
Swap int double.jpg


thanks
 
Technology news on Phys.org
  • #2
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);
}
 
  • Like
Likes yungman
  • #3
ints are not doubles.
pointers to ints are not pointers to doubles.
 
  • #4
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:
  • #5
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:
  • Like
Likes yungman
  • #6
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
 
  • #7
Mark44 said:
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.

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

Thanks
 
  • #8
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:
  • Like
Likes yungman
  • #9
yungman said:
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.
 
  • Like
Likes yungman
  • #10
Mark44 said:
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:
Ivor1.jpg


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
 
  • #11
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:
  • Like
Likes yungman
  • #12
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."
yungman said:
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.
yungman said:
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.
 
  • Like
Likes yungman
  • #13
Filip Larsen said:
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.
 
  • Like
Likes Filip Larsen
  • #14
Mark44 said:
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
 
  • #15
jbunniii said:
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
 
  • #16
Copied from post #12:
Mark44 said:
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
yungman said:
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.
 
  • Like
Likes yungman
  • #17
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
 
  • #18
yungman said:
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.
 
  • #19
Vanadium 50 said:
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.
 
  • #20
yungman said:
Read the question again.

Tell ya' what. I'll read your questions again if you read our answers once.
 
  • #21
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!
 
  • #22
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:
Ivor1.jpg

Here is book introducing explicit argument using program 9.1 above:
Ivor.jpg


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.5BUT 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.
Swap int double.jpg


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:
template error.jpg
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
 
  • #23
yungman said:
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).
yungman said:
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.
yungman said:
So my latest idea is to put var1 and var2 as global
Bad idea.
yungman said:
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.
 
  • Like
Likes yungman
  • #24
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
 
  • #25
yungman said:
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.
yungman said:
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?
yungman said:
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.
 
  • #26
Mark44 said:
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?
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.

Mark44 said:
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:

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.

I read this a few times, I don't understand what you are talking at all. Forget about swapping two things, I am talking about declaring type and object now.
 
  • #27
yungman said:
But with template, I cannot do that.

It may be that Mark or others in this thread have already tried to explain this, but you seem to have missed an important thing about templated definitions (templated functions, classes, methods, types, etc), namely that until all template parameters have been provided (bound to a specific type or value) in a specific usage of the templated definition then it is not yet instantiated or "compiled in" yet.

For example if you say template <class T> T square(T x) { return x*x;} then this definition is not a real function you can call (the template will not be instantiated) until you provide the type, e.g. by calling with square(2.0) where T then is implicitly bound to double for that instance of the template. You can think of the templated definition of square as a generator that will generate a specific function when it is instantiated. This also means that if you call square(2.0) and also square(2) then conceptually your code will behave as if two unrelated functions had been compiled in, namely square_double(double x) and square_int(int x) (in practice they are not given such simple names, but that is "just details").

So, if you try to write template <class T> T variable; then, even if this was valid code, it would only define a "generator" and not any specific "instance" of a variable. Compare this with the valid way to make a pair of equal-typed variables via, say, a templated struct:
C++:
template <class T>
struct my_pair { // templated type, no code or variables generated (yet)
  T a;
  T b;
};

int main() {
  my_pair<int> p; // here the templated type is instantiated with type [ICODE]int[/ICODE].
  p.a = 6; p.b = 4;
}
 
  • Like
Likes yungman
  • #28
Thanks Filip
Yes, I missed that template is only a mold where a function is instantiated. I still don't quite get it. The example below doesn't work if I have both function swapVars() and larger(). But individually, it runs fine.
C++:
#include <iostream>
#include <string>
using namespace std;
template<class T>
void swapVars(T &var1, T &var2)//function template for swapVars
{    T temp;
    temp = var1;
    var1 = var2;
    var2 = temp;
}

T larger(T a, T b)//function template for larger
{
if (a > b) return a;
else if (b > a)return b;
return a;
}
int main()
{ //next two lines are for larger() only
    int big=4,small=1;
    cout<<" larger of big and small is: "<<larger(big, small)<<endl;

//next 3 lines are for swapVars() only.
    int a = 2, b = 3;
    swapVars(a, b);
    cout << " After swapping " << a << ", " << b << endl;
    return 0;
}

If I get rid of all the swapVars() lines, the program will run for larger() function. If I get rid of all the larger() lines, the program will run for swapVars(). But it won't even compile if I have both in the program. Why can't I have two function templates in the program?

Thanks
 
  • #29
yungman said:
Why can't I have two function templates in the program?
If you want two function templates how many times do you think you would have to use the keyword template? How many times have you used it?

What you are trying to do is pointless anyway; a function that swaps two variables passed by reference prevents compiler optimization.

And where did you get the idea that passing variables by reference is a way to return two variables from a function? It is not; unlearn this.
 
  • Like
Likes Vanadium 50
  • #30
pbuk said:
And where did you get the idea that passing variables by reference is a way to return two variables from a function?
As I'm sure you know, function whose parameters are passed by reference, either as C++ references or as pointers, can modify its actual parameters, as in the following example. Strictly speaking, the function below doesn't return anything, but when it returns a has been increased by 1 and b has been increased by 2.

That's the sense in which @yungman meant that a function could "return" two values.

C++:
void alterTwoVars(int& x, int& y)
{
    x += 1;
    y += 2;
}
int main()
{
    int a = 3, b = 5;
    alterTwoVars(a, b);
}
 
  • Like
Likes yungman
  • #31
Mark44 said:
As I'm sure you know, function whose parameters are passed by reference, either as C++ references or as pointers, can modify its actual parameters, as in the following example. Strictly speaking, the function below doesn't return anything, but when it returns a has been increased by 1 and b has been increased by 2.

That's the sense in which @yungman meant that a function could "return" two values.

C++:
void alterTwoVars(int& x, int& y)
{
    x += 1;
    y += 2;
}
int main()
{
    int a = 3, b = 5;
    alterTwoVars(a, b);
}
Yes, They are passed by reference so it's NOT returning anything.

I have been reading the books over, it is still not clear to me why I cannot have two functions with only one template<class T> declaration. My understanding is when you make this declaration, meaning the function that use T data type becomes a "mold" or blue print of a function. Then in the program, compiler will search the function name ( like swapVars or larger) and instantiate the object accordingly. So why can't I define 2 function with T?

Another question I want to clarify, template ONLY work on function, ADT like struct and class, it is NOT for declaring variable type like what I did T a; to declare a is T type that I can make it int, double, string variable in the program.

Thanks
 
  • #32
pbuk said:
If you want two function templates how many times do you think you would have to use the keyword template? How many times have you used it?
 
  • #33
I know what you are getting to. As I wrote in the last post, all the books said it's a blue print, none say you can only make one function out of the mold.
 
  • #34
yungman said:
I know what you are getting to.
Do you? You have said that you have understood things in the past but have later demonstrated that you have not. This time, if you want to learn, answer the questions.

Q1. If you want two function templates how many times do you think you would have to use the keyword template?

Q2. How many times are you using the keyword template?
 
  • #35
I think I get it, let me verify

The function should be written like
C++:
template<class T>  T larger(T &x, T &y){}//in one line because they have to go together

It is deceiving to written like this as it looks like two individual lines:
C++:
template<class T>//not a separate line
T larger(T & x, T &y){}

That I should read it as one line. Am I right? This will make a world of sense, that they both goes together, that you have to write this every time.

That template<class T> is NOT like a general declaration that "you are using template in this program".
 
<H2>1. What is a function template?</H2><p>A function template is a generic function that can be used with different data types. It allows for code reusability and flexibility by allowing the same function to work with different types of data.</p><H2>2. How can a function template solve complications with mixing types for variable swapping?</H2><p>A function template can use template parameters to specify the data types of the variables being swapped. This ensures that the correct type conversions are performed, preventing any complications that may arise from mixing different types of data.</p><H2>3. What are the benefits of using a function template for variable swapping?</H2><p>Using a function template for variable swapping can improve code efficiency and reduce the need for writing multiple functions to handle different data types. It also allows for easier maintenance and updates to the code.</p><H2>4. Can function templates be used for more than just variable swapping?</H2><p>Yes, function templates can be used for a variety of tasks such as sorting, searching, and mathematical operations. They can also be used with user-defined data types.</p><H2>5. Are there any limitations to using function templates for variable swapping?</H2><p>One limitation is that function templates may not be suitable for all scenarios, particularly when dealing with complex data types or when precise control over type conversions is needed. In these cases, a specialized function may be more appropriate.</p>

1. What is a function template?

A function template is a generic function that can be used with different data types. It allows for code reusability and flexibility by allowing the same function to work with different types of data.

2. How can a function template solve complications with mixing types for variable swapping?

A function template can use template parameters to specify the data types of the variables being swapped. This ensures that the correct type conversions are performed, preventing any complications that may arise from mixing different types of data.

3. What are the benefits of using a function template for variable swapping?

Using a function template for variable swapping can improve code efficiency and reduce the need for writing multiple functions to handle different data types. It also allows for easier maintenance and updates to the code.

4. Can function templates be used for more than just variable swapping?

Yes, function templates can be used for a variety of tasks such as sorting, searching, and mathematical operations. They can also be used with user-defined data types.

5. Are there any limitations to using function templates for variable swapping?

One limitation is that function templates may not be suitable for all scenarios, particularly when dealing with complex data types or when precise control over type conversions is needed. In these cases, a specialized function may be more appropriate.

Similar threads

  • Programming and Computer Science
Replies
19
Views
2K
  • Programming and Computer Science
Replies
4
Views
753
  • Programming and Computer Science
Replies
1
Views
628
  • Programming and Computer Science
2
Replies
39
Views
3K
  • Programming and Computer Science
Replies
4
Views
3K
  • Programming and Computer Science
Replies
1
Views
598
  • Programming and Computer Science
3
Replies
89
Views
4K
  • Programming and Computer Science
Replies
20
Views
1K
  • Programming and Computer Science
Replies
15
Views
2K
  • Programming and Computer Science
2
Replies
35
Views
2K
Back
Top