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:
  • #36
I am taking the time to help you, take the time to answer my questions.
 
  • Love
Likes Vanadium 50
Technology news on Phys.org
  • #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
  • #61
Don't tell me in this case, cheapness doesn't pay. I downloaded Gaddis 6th edition for free, it has nothing of this kind at all. Wow, maybe I should pay some money and get a newer version. Now I have to guess reading codes!

Not just loop range based or the if else statement explained before. Don't they have a general name for this kind of simplified code. I just want to find a website that show the translation. I don't even know the name. I hate to ask every time I encounter this kind of simplified code. I am sure I can learn it just like that if I can have a table of translation.

Thanks
 
  • #62
yungman said:
Don't tell me in this case, cheapness doesn't pay. I downloaded Gaddis 6th edition for free, it has nothing of this kind at all.
Gaddis's 6th ed. is copyrighted 2009, before the changes in C++. As John Arbuckle once said, "You get what you pay for." (Catch phrase used in ads for Yuban coffee)
yungman said:
Don't they have a general name for this kind of simplified code.
Not sure which simplified code you're asking about. Do you mean the braced initializer list (e.g.,
T result{ data[0] }; ) ?
 
  • Like
Likes Vanadium 50
  • #63
yungman said:
Don't they have a general name for this kind of simplified code.
New features? C++ is a constantly evolving language, any book will become out of date.

yungman said:
I just want to find a website that show the translation.
I mostly use cppreference.com. As you can see there are new features introduced in c++20 (for example the spaceship operator), and there will be more coming in c++23.
 
  • Like
Likes yungman
  • #64
Hi

I have been working on new stuffs using the book by Ivor, things that I never learned because the Gaddis I use is too old. So I have to take a detour to learn those. I think I cover the function templates quite well at this point. I just want to verify with you guys on my notes I have on typeid(), auto, decltype() and Trailing return type.

I find I like GeekForGeeks the best. It's the easiest to understand.

I attached my notes, I hope I am correct, if not, please let me know.

Thanks
 

Attachments

  • typeid auto decltype.docx
    18.7 KB · Views: 227

Similar threads

Replies
19
Views
3K
Replies
39
Views
4K
Replies
89
Views
5K
Replies
15
Views
2K
Replies
35
Views
3K
Back
Top