Function Template: Solve Complications with Mixing Types for Variable Swapping

  • Thread starter Thread starter yungman
  • Start date Start date
  • Tags Tags
    Function
Click For Summary
The discussion revolves around the challenges of using templates in C++ to swap variables of different types, specifically when using references. The original attempt to swap an integer and a double using a template function resulted in compilation errors due to type incompatibility with references. A proposed solution involves creating a template function that accepts two different types as parameters, allowing for the swapping of mixed types. The conversation also touches on the importance of understanding how templates work and the need for explicit type casting when dealing with different data types. Ultimately, the participants emphasize the significance of learning and applying templates correctly in programming.
  • #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
 
Technology news on Phys.org
  • #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".
 
  • #36
I am taking the time to help you, take the time to answer my questions.
 
  • Love
Likes Vanadium 50
  • #37
pbuk said:
I am taking the time to help you, take the time to answer my questions.
I thought I answer, the two lines has to go together, so you have to write template<class T> for every function declaration.
 
  • #38
I'll make it easier for you, multiple choice:

Q1. If you want two function templates how many times do you think you would have to use the keyword "template"? (a) one (b) two (c) some other number

Q2. How many times are you using the keyword "template"? (a) one (b) two (c) some other number
 
  • Like
Likes Vanadium 50
  • #39
pbuk said:
I'll make it easier for you, multiple choice:

Q1. If you want two function templates how many times do you think you would have to use the keyword "template"? (a) one (b) two (c) some other number

Q2. How many times are you using the keyword "template"? (a) one (b) two (c) some other number
1) If I am correct in post 35, then (a) one for each function, you can have two function and use two.

2) as 1).
 
  • #40
"one for each function" is not an option. The options are (a) one (b) two (c) some other number.
 
  • #41
pbuk said:
"one for each function" is not an option. The options are (a) one (b) two (c) some other number.
I know what you want me to say, it's one. But I don't know why. I thought this is ok also.
C++:
template<class T> T larger(T &a, T &b){}
template<class T> voide swapVars(T &a, T &b){}

If this is not correct, I am still missing something that I don't understand and I cannot find it in the books.
 
  • #42
Or I have to do this for two functions
C++:
template<class T1, class T2>
T1 larger(T1 &a, T1 &b){}
void swapVars(T2 &a, T2 &b){}

That I can only use T1 ones and T2 ones?

See, this is what I don't understand why. I don't want to answer by guessing.
 
  • #43
yungman said:
If this is not correct, I am still missing something that I don't understand and I cannot find it in the books.
That is because the problem is not in the books, it is in your head. I can help you solve this but only when you accept that the way to learn is not to present me with what you think you know or what you think you want me to hear, it is simply to answer the question. One letter will do, a, b or c:

If you want two function templates how many times do you think you would have to use the keyword template? (a) one (b) two (c) some other number?
 
  • #44
pbuk said:
That is because the problem is not in the books, it is in your head. I can help you solve this but only when you accept that the way to learn is not to present me with what you think you know or what you think you want me to hear, it is simply to answer the question. One letter will do, a, b or c:

If you want two function templates how many times do you think you would have to use the keyword template? (a) one (b) two (c) some other number?
It is one.

My question is why?

It is obvious, it's not helping if I have no idea why.
 
  • Love
Likes pbuk
  • #45
Please don't make fun of this, I have been struggling on this for a few days and I cannot find the answer. I am stuck.
 
  • #46
Ok, that is wrong. If you want two function templates you have to use the keyword template twice.

I have quite a lot more to give you here, but here is a start as to why: (taken from http://www.cplusplus.com/doc/oldtutorial/templates/ - I will try and get a more up to date source)
The format for declaring function templates with type parameters is:

C++:
template <class identifier> function_declaration;
or
C++:
template <typename identifier> function_declaration;

So each function declaration requires its own 'template' keyword and a class or typename identifier as appropriate. The class or typename identifier only has a meaning within the function definition with which it is associated (i.e. that is its scope).
 
  • Like
Likes yungman
  • #47
pbuk said:
Ok, that is wrong. If you want two function templates you have to use the keyword template twice.

I have quite a lot more to give you here, but here is a start as to why: (taken from http://www.cplusplus.com/doc/oldtutorial/templates/ - I will try and get a more up to date source)So each function declaration requires its own 'template' keyword and a class or typename identifier as appropriate. The class or typename identifier only has a meaning within the function definition with which it is associated (i.e. that is its scope).
Thanks, I have to spend some time reading it. I'll be back.

Thanks
 
  • #48
No, don't go away! I'll help you go through it: let's stick with that guide.
 
  • #49
So we have read that a function template has three parts:
  1. the template keyword
  2. a declaration in the form <class identifier> or <typename identifier> (it goes on to say that it doesn't matter which form you use but the examples use <class> so we will stick with that for the time being)
  3. a function_declaration
It then gives an example:
C++:
template <class myType>
myType GetMax (myType a, myType b) {
  return (a>b?a:b);
}
 
  • #50
You can see that the example has been split over 4 lines; it could just as easily have been written
C++:
template <class myType> myType GetMax (myType a, myType b) { return (a > b ? a : b); }
or
C++:
template
  <class myType>
  myType GetMax (myType a, myType b)
    {
      return (a > b ? a : b);
    }
or even
C++:
template
  <class
    myType>
  myType
    GetMax (
      myType
        a,   // a is the first argument
      myType
        b    // b is the second
    )
    {
      return
        (
          a > /* that sign means greater than */ b
          ? a
          : b
        );
    }
 
  • #51
The third example would be ridiculous of course, I only wrote it to demonstrate that in c++ the amount of whitespace (i.e. spaces, tabs and new lines) separating symbols doesn't matter - pretty much anywhere we can put a space, we can start a new line, and anywhere we have a new line we can replace it with a space.

The important exceptions to this are compiler directives, which are not actually part of c++ itself, and these always start with # as the first character of a new line, and in // style comments which are terminated by the first following newline.

So to summarise, it doesn't matter how you lay out the template function declaration, it must always consist of exactly 3 parts separated by whitespace:
C++:
template <class identifier> function_declaration;
// or
template <typename identifier> function_declaration;

We can of course have as many template function definitions as we like: each one must start with the template keyword, followed by a class or typename identifier, followed by a function declaration.
 
Last edited:
  • #52
Hi Pbuk

Thanks for all the info, I have been out and busy the whole day, this is the first change I even get to print it out and read it. I'll read your posts and I'll be back tomorrow.

Thanks so much. Sorry I did not come back sooner.
 
  • #53
Thank you so much Pbuk. I got it. You verify that my guess in post 35 is correct. Finally it makes sense that template<class T> has to go together with the function. This is what I missed before. I actually made this program with the modification and it works:
C++:
#include <iostream>
using namespace std;
template<class T>  void swapVars(T &var1, T &var2)
{    T temp;
    temp = var1;
    var1 = var2;
    var2 = temp;
}
template<class T> T larger(T var3, T var4)
{
    if (var3 > var4) return var3;
    else if (var4 > var3)return var4; 
    return var3;
}

int main()
{
    int a=4,b=1;//test T as int
    cout<<" larger of big and small is: "<<larger(a, b)<<endl;

    double c = 2.1, d = 3.5;//testing T is double
    swapVars(c, d);
    cout << " After swapping " << c << ", " << d << endl;
    return 0;
}

I like to write template<class T> void swapVars(T &var1, T &var2) in one line to remind me they have to go together. I even made the two function templates so one work on int and the other work on double to proof I can use template<class T> and don't have to make it template<class T1, class T2> to accommodate two functions.

Finally, you wrote return (a>b?a:b). What do you call this form: (a>b?a:b)? I would have to write in long form:
C++:
if(a>b) return a;
else return b;

I want to learn how to write in this form, I don't even know what you call that so I can't even search online.

Thanks so much.
 
  • #54
  • Like
Likes yungman
  • #55
yungman said:
I like to write template<class T> void swapVars(T &var1, T &var2) in one line to remind me they have to go together.
In this case I think I agree with you - it is clearer and it doesn't make the line too long.
 
  • Like
Likes yungman
  • #56
Thanks so my Pbuk, now I have no issue working through template so far.

But I have questions on the "short" form of writing statements like the a>b ? a:b type. seems like there is a new way of writing program from what I learn in the old Gaddis book. I don't even know what you call these. Last time when I asked you, that turn out to be a very specific if else statement, but there are a lot more like the example below. What do you call those simplified statement. I need to learn this.

Below are a few examples I have no idea where they come from. I put the questions in the comments:
C++:
#include<iostream>
#include<vector>
using namespace std;
template<typename T1, typename T2>
? ? ? larger(T1 a, T2 b)// what is ?
{
    return a > b ? a : b;
}

template<typename T1, typename T2>
auto larger(T1 a, T2 b)// what is auto
{
    return a > b ? a : b;
}

template<type T> T larger(const vector<T>& data)
{
    T result{ data[0] }; //why not T result = data[0]?
    for(auto& value : data)//what is this?
    {
        if (value > result)result = value;
    }
    return result;
}

Note that it's not the template that I have question, it's the short form statement that I don't get.

I want to get the name of this short form so I can look up and learn. Without the name, I don't even know what to look.

Thanks so much for helping.
 
  • #57
The <condition> ? <expression> : <expression> form is called a ternery condition, or look up ternery operator. Auto means it doesn't check the type that is returned from the function (note that if a > b then a will be returned which has type T1 otherwise b will be returned which has type T2).

That's two for you to get started on.
 
  • #58
yungman said:
But I have questions on the "short" form of writing statements like the a>b ? a:b type.
As pbuk already noted, this is the conditional operator, also called the ternary operator because it has three operands. This operator has been present in C from the beginning, and was inherited by C++. It's also present in Java, C#, Python, Perl, and probably a few others.

The expression a > b ? exp1 : exp2 consists of three parts:
  1. The first part (a > b above) is a Boolean expression, one that evaluates to true or false.
  2. The second part (exp1).
  3. The third part (exp2).
If the Boolean expression is true, the conditional expression evaluates to exp1.
If the Boolean expression is false, the conditional expression evaluates to exp2.

C++:
int pets = 2;
std::cout << "I have " << pets << " pet" << (pets > 1 ? 's' : '\0') << std::endl;

If pets is 1, the conditional expression evaluates to the null character, and the output will be "I have 1 pet". If pets is 2, conditional expression evaluates to the character literal 's', and the output will be "I have 2 pets", and similar for other integers larger than 1. Additional logic would be needed if pets is 0 or negative.

The Gaddis book, "Starting out with C++, from Control Structures through Objects," 6th Ed, shows the conditional operator on the 2nd page of the book, and in section 4.14, starting on page 218.
 
  • Like
Likes Vanadium 50
  • #59
Mark44 said:
As pbuk already noted, this is the conditional operator, also called the ternary operator because it has three operands. This operator has been present in C from the beginning, and was inherited by C++. It's also present in Java, C#, Python, Perl, and probably a few others.

The expression a > b ? exp1 : exp2 consists of three parts:
  1. The first part (a > b above) is a Boolean expression, one that evaluates to true or false.
  2. The second part (exp1).
  3. The third part (exp2).
If the Boolean expression is true, the conditional expression evaluates to exp1.
If the Boolean expression is false, the conditional expression evaluates to exp2.

C++:
int pets = 2;
std::cout << "I have " << pets << " pet" << (pets > 1 ? 's' : '\0') << std::endl;

If pets is 1, the conditional expression evaluates to the null character, and the output will be "I have 1 pet". If pets is 2, conditional expression evaluates to the character literal 's', and the output will be "I have 2 pets", and similar for other integers larger than 1. Additional logic would be needed if pets is 0 or negative.

The Gaddis book, "Starting out with C++, from Control Structures through Objects," 6th Ed, shows the conditional operator on the 2nd page of the book, and in section 4.14, starting on page 218.
Yes, I understand that already, it's the other news ones in my post.

Thank
 
  • #60
yungman said:
Yes, I understand that already, it's the other news ones in my post.
Maybe it's some of these:
C++:
template<typename T1, typename T2>
? ? ? larger(T1 a, T2 b)// what is ?
{
    return a > b ? a : b;
}
I don't think this is meant to be actual code. As far as I can tell, the ? is just a placeholder for some type.

C++:
template<typename T1, typename T2>
auto larger(T1 a, T2 b)// what is auto
{
    return a > b ? a : b;
}
This is actual code. @pbuk explained what the keyword auto means here.

C++:
template<type T> T larger(const vector<T>& data)
{
    T result{ data[0] }; //why not T result = data[0]?
    for(auto& value : data)//what is this?
    {
        if (value > result)result = value;
    }
    return result;
}
T result{ data[0]}; has the same effect as T result = data[0];
The intent is to initialize result to the value in data[0].

This type of for loop is something fairly new in C++, possibly introduced in C++11, but I'm not certain of that. It's called a range-based for loop. Here's more information - Range-based for Statement (C++) | Microsoft Docs
 
  • Like
Likes yungman

Similar threads

  • · Replies 19 ·
Replies
19
Views
6K
  • · Replies 4 ·
Replies
4
Views
1K
  • · Replies 0 ·
Replies
0
Views
582
  • · Replies 39 ·
2
Replies
39
Views
5K
  • · Replies 89 ·
3
Replies
89
Views
6K
Replies
20
Views
2K
Replies
4
Views
5K
  • · Replies 0 ·
Replies
0
Views
1K
  • · Replies 35 ·
2
Replies
35
Views
4K
  • · Replies 15 ·
Replies
15
Views
3K