-
C++ Templates: The Complete Guide
Hello,
I purchased this book hoping to gain a further understanding in templates. But my issue is that, a lot of the code that the book says WONT compile, ... does. Such as the following -
Code:
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
return max (max(a,b), c); // uses the template version even for ints
} // because the following declaration comes
// too late:
// maximum of two int values
inline int const& max (int const& a, int const& b)
{
return a < b ? b : a;
}
Which calls the int function for me on VS2008, CodeBlocks and DevC++. Where i had the latter 2 set to the GCC compiler. Other issues are examples where although the book says i need to use typename for some dependant type, VS2008 doesnt require it.
Im not sure if this is due to the book being out of date or what. But i was wondering if you could give me some advice as to how i should continue. Should i keep reading? is there some other more up to date material that these compilers are conforming too?
thanks
-
Re: C++ Templates: The Complete Guide
I'm using VS2008 also, and I have experience but don't have handy GCC of various versions.
In my own work I've seen there are differences between these two compilers regarding the tolerance of the order of appearance for template classes and functions. VS2008 is the less restrictive. Code which VS2008 compiles might cause GCC to complain, but to date I've found that when GCC accepts it, VS2008 has no problem.
I haven't tried this since 3.x, since I always took some care in this regard, but if your code were:
Code:
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
return max (max(a,b), c); // uses the template version even for ints
} // because the following declaration comes
// too late:
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
I might expect VS2008 to accept this (and it did), but GCC might not.
This, on the other hand
Code:
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
return max (max(a,b), c); // uses the template version even for ints
} // because the following declaration comes
// too late:
Is likely to pass both compilers just fine.
Since the template max with two parameters also does what the int version in your code does, I'd expect the illustration would not fail at all.
To your broader question, while I don't know the book you're using, if it's published after 2004 it's probably relevant. Heck, if it was current with C++ as of 1999 it may be relevant, but offer the caveat that a compiler like VC6 (which was still the Visual Studio version of that day) might have a lot more trouble than any of the recent versions.
-
Re: C++ Templates: The Complete Guide
Hm when you say
Quote:
Originally Posted by
wheelie
Hello,
I purchased this book hoping to gain a further understanding in templates. But my issue is that, a lot of the code that the book says WONT compile, ... does. Such as the following -
and go on to say
Quote:
Which calls the int function for me on VS2008, CodeBlocks and DevC++.
what are you trying to say?
Are you saying that you'd get a compilation error compiling just the code,
or when you actually try to call the function?
Either way, be more specific in what you're trying to do so that we can understand the problem better.
Quote:
Other issues are examples where although the book says i need to use typename for some dependant type, VS2008 doesnt require it.
what do you mean?
-
Re: C++ Templates: The Complete Guide
Quote:
Which calls the int function for me on VS2008
Template code needs to be called and/or instantiated first before concluding the code compiles or not. I see no instantiation of any templates or calls to the template functions in the code that you posted. Many compilers will not compile template code unless the template code is actually being called -- instead the compiler will indicate that there are "no errors", giving you the feeling that the template code is OK (when it could be riddled with compiler errors).
Secondly, just because a compiler may compile some code doesn't mean the compiler is right and the authors are wrong..
Quote:
Other issues are examples where although the book says i need to use typename for some dependant type, VS2008 doesnt require it.
That doesn't mean that VS2008 is correct. VC 6.0 never required "typename" at all. It doesn't mean it is correct.
Regards,
Paul McKenzie
-
Re: C++ Templates: The Complete Guide
Sorry guys, i do apologise, bad wording on my part. What i meant to say was that the code does compile, but when instantiated, doesn't behave as described by the authors.
Concerning the above code, which can be found on the authors site Here
When compiled as follows, it does seem to call the int function which the authors say it wont.
Code:
#include <iostream>
using namespace std;
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
cout << "inline T const& max (T const& a, T const& b)" << endl;
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
cout << "inline T const& max (T const& a, T const& b, T const& c)" << endl;
return max (max(a,b), c); // uses the template version even for ints
} // because the following declaration comes
// too late:
// maximum of two int values
inline int const& max (int const& a, int const& b)
{
cout << "inline int const& max (int const& a, int const& b)" << endl;
return a < b ? b : a;
}
int main()
{
int a, b, c;
a = 1; b = 2; c = 3;
max(a,b,c);
getchar();
return 0;
}
And for my example of typenames, i was meaning this sort of situation, where the authors mention that using the keyword typename is required for dependant types, to specify that they are indeed an actual type rather than some member.
Yet works fine without it.
Code:
class A
{
public:
typedef int IntType;
};
template < typename T >
void Func( T t )
{
/* typname */ T::IntType i = 6; //book specifies that the keyword is required
cout << i ;
}
int main()
{
A a;
Func(a);
getchar();
return 0;
}
Quote:
Secondly, just because a compiler may compile some code doesn't mean the compiler is right and the authors are wrong..
I wasnt trying to say that, im simply asking how i can study a subject that doesnt seem to behave as books on the subject say it is suppose too. Whether it be due to the compiler not conforming or not, it makes it difficult to experiment when things go differetly to the training material.
How have you guys been learning it?
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by wheelie
im simply asking how i can study a subject that doesnt seem to behave as books on the subject say it is suppose too. Whether it be due to the compiler not conforming or not, it makes it difficult to experiment when things go differetly to the training material.
You can try disabling language extensions and setting the warning level to the maximum. You can also compile your test programs with another compiler (e.g., the MinGW port of GCC and/or the Comeau online compiler) to see if there is a difference.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
wheelie
Hello,
I purchased this book hoping to gain a further understanding in templates. But my issue is that, a lot of the code that the book says WONT compile, ... does. Such as the following -
Code:
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
return max (max(a,b), c); // uses the template version even for ints
} // because the following declaration comes
// too late:
// maximum of two int values
inline int const& max (int const& a, int const& b)
{
return a < b ? b : a;
}
Which calls the int function for me on VS2008, CodeBlocks and DevC++. Where i had the latter 2 set to the GCC compiler. Other issues are examples where although the book says i need to use typename for some dependant type, VS2008 doesnt require it.
Im not sure if this is due to the book being out of date or what. But i was wondering if you could give me some advice as to how i should continue. Should i keep reading? is there some other more up to date material that these compilers are conforming too?
thanks
I think you should use whatever compiler the book recommends. If it doesn't recommend any, then find a book that does. In my experience, visual has a lot of unique quirks that are learned with experience. If that makes it tough for you to learn something new, then use a different compiler when learning a new topic.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
wheelie
Sorry guys, i do apologise, bad wording on my part. What i meant to say was that the code does compile...
Here is what the Comeau on-line compiler has to say about this code:
Code:
Thank you for testing your code with Comeau C/C++!
Tell others about http://www.comeaucomputing.com/tryitout !
Your Comeau C/C++ test results are as follows:
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
"ComeauTest.c", line 17: error: more than one instance of overloaded function "max"
matches the argument list, the choices that match are:
function template "const T &max(const T &, const T &)"
function template "const _Tp &std::max(const _Tp &, const _Tp &)"
The argument types that you used are: (const int, const int)
return max (max(a,b), c); // uses the template version even for ints
^
detected during instantiation of "const T &max(const T &, const T &,
const T &) [with T=int]" at line 31
"ComeauTest.c", line 17: error: no instance of overloaded function "max" matches the
argument list
The argument types that you used are: (<error-type>, const int)
return max (max(a,b), c); // uses the template version even for ints
^
detected during instantiation of "const T &max(const T &, const T &,
const T &) [with T=int]" at line 31
2 errors detected in the compilation of "ComeauTest.c".
In strict mode, with -tused, Compile failed
So it doesn't compile wth the Comeau compiler, and Comeau is one of, if not, the most compliant ANSI C++ compiler out there. In addition, your original code you posted did "compile" OK using the Comeau compiler -- this stresses my point that template code must be instantiated somewhere before it can be verified that the code compiles fine or not.
I would believe the book. The authors of the book (Josuttis and Vandevoorde) are two expert C++ programmers who actually study compliancy, language rules, etc. It isn't easy just to dismiss their books. If there is an error, an errata would have been posted (as Josuttis has done with his other book "The C++ Standard Library").
Also, for g++ turn off all the language extensions and compile using the ANSI mode. If you don't do that, even this compiles correctly:
Code:
int main()
{
int n = 10;
int array[n]; // This is an error, but g++ compiles this if you do not turn on the ANSI mode.
}
Regards,
Paul McKenzie
-
Re: C++ Templates: The Complete Guide
I have just tested the following code with both VS and GCC:
Code:
#include <iostream>
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
std::cout << "T const& max (T const& a, T const& b)" << std::endl;
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
std::cout << "T const& max (T const& a, T const& b, T const& c)" << std::endl;
return max (max(a,b), c); // uses the template version even for ints
} // because the following declaration comes
// too late:
// maximum of two int values
inline int const& max (int const& a, int const& b)
{
std::cout << "int const& max (int const& a, int const& b) " << std::endl;
return a < b ? b : a;
}
int main()
{
int a(0);
int b(0);
int c(0);
std::cout << max(a,b,c) << std::endl;
std::cin.get();
}
GCC generates the expected result:
Quote:
T const& max (T const& a, T const& b, T const& c)
T const& max (T const& a, T const& b)
T const& max (T const& a, T const& b)
0
But VS2008 generates the following output (with and without language extensions disabled)
Quote:
T const& max (T const& a, T const& b, T const& c)
int const& max (int const& a, int const& b)
int const& max (int const& a, int const& b)
0
I must admit, I find this behavior concerning.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
PredicateNormative
I have just tested the following code with both VS and GCC:
You're testing code that, according to Comeau (and the book in question), shouldn't even exist. Therefore if you produced an executable from code that is invalid, anything can happen.
Regards,
Paul McKenzie
-
Re: C++ Templates: The Complete Guide
When I paste PredicateNormative's code into Comeau it gives...
In strict mode, with -tused, Compile succeeded (but remember, the Comeau online compiler does not link).
Compiled with C++0x extensions enabled.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
JohnW@Wessex
When I paste PredicateNormative's code into Comeau it gives...
In strict mode, with -tused, Compile succeeded (but remember, the Comeau online compiler does not link).
Compiled with C++0x extensions enabled.
My mistake. I thought that the OP's new code was being tested.
Regards,
Paul Mckenzie
-
Re: C++ Templates: The Complete Guide
This puzzle is intriguing.
From a logical perspective, aside from C++ standards documentation, this code does present a seeming conundrum.
We have max in a "standard" function operating on int, and a comparable template function max for any type, which logically conflict (though these examples do the same thing) when T is int.
I would expect the compiler to favor the "standard" max for int, rather than generate a template - because the application code has called max on int for which there's no need to search for a solution by generating the template.
For other types, obviously, the function max wouldn't be found unless the template were generated.
Why, then, would any compiler (or the standard) result in logic where the template would be generated when a suitable function is already fully defined to satisfy the call?
To that end, the visual studio result SEEMS reasonable, even if it violates the standard.
Now, not having read the book, I would view this example of a subtle logical error in programming - an alias, if you will, of the max function which could be satisfied by two approaches, creating a logical conundrum which would need either an arbitrary solution, or rejection because of the paradox. I can see why the compiler might not reject the two versions of max (the name mangled identifiers are different), while the ambiguity at the point of the call to max can be logically satisfied by choosing to avoid the extra work of generating a template when the call can be satisfied, something like we'd expect from a template specialization (which can't be done with functions).
I think it's an example of what not to do, but I must admit I find it disconcerting that VS simply makes a choice and goes right on.
Indeed, with language extensions off, warnings at 4 and code analysis turned on, all VS complains about are unreferenced formal parameters.
If the function in question were not max, but any function, and the code for the template and non-template versions were entirely unrelated (as in this happened because of a real oversight in development), the results would be compiler dependent, give no warning, and it could be quite a subtle bug which I've never considered before (commonly using the VS compiler as I do).
Fortunately I build cross platform stuff, and typically do check with other compilers, but here's another interesting difference among them.
-
Re: C++ Templates: The Complete Guide
First and foremost, let's not forget we already have max function in our standard namespace.
OP's code fails on Comeau, GCC (minGW port), but compiles on VS2008 (with warning lv4, and extension disabled)
PredicateNormative's code compiles on all three.
The difference is that OP uses using directive while PredicateNormative qualifies a full name
(effectively eliminating name collision).
So the problem stems from the name collision and confuses the compiler in finding best match.
@wheelie:
Notice how Josuttis doesn't use "using namespace std", but you do.
when you introduce std namespace at a global scope, take precaution,
especially when you design classes/functions that are so commonly used by other developers.
Designing a set of overloads involving template and non-templates is tricky (and hard)
especially when the the types of arguments are closely related by conversion.
You need to understand function matching thoroughly,
and need to know where and at what stage(s) of overload resolution the ambigous call can occur
Code:
class A
{
public:
typedef int IntType;
};
template < typename T >
void Func( T t )
{
/* typname */ T::IntType i = 6; //book specifies that the keyword is required
cout << i ;
}
int main()
{
A a;
Func(a);
return 0;
}
this fails to compile on all three, so I thnk Josuttis is correct.
Last but not the least,
prefer a set of template specialization over overloading a set of template and non-template combined.
-
Re: C++ Templates: The Complete Guide
Quote:
So the problem stems from the name collision and confuses the compiler in finding best match.
@wheelie:
Notice how Josuttis doesn't use "using namespace std", but you do.
when you introduce std namespace at a global scope, take precaution,
especially when you design classes/functions that are so commonly used by other developers.
It still gives me the same result in vs2008
inline T const& max (T const& a, T const& b, T const& c)
inline int const& max (int const& a, int const& b)
inline int const& max (int const& a, int const& b)
Press any key to continue . . .
Code:
#include <iostream>
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
std::cout << "inline T const& max (T const& a, T const& b)" << std::endl;
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
std::cout << "inline T const& max (T const& a, T const& b, T const& c)" << std::endl;
return max (max(a,b), c); // uses the template version even for ints
} // because the following declaration comes
// too late:
// maximum of two int values
inline int const& max (int const& a, int const& b)
{
std::cout << "inline int const& max (int const& a, int const& b)" << std::endl;
return a < b ? b : a;
}
int main()
{
int a, b, c;
a = 1; b = 2; c = 3;
max(a,b,c);
getchar();
return 0;
}
Also, are you saying that the following didnt compile for you in VS2008? It still compiles for me, only with warnings, with lvl4 and extensions disabled
Code:
#include <iostream>
class A
{
public:
typedef int IntType;
};
template < typename T >
void Func( T t )
{
/* typname */ T::IntType i = 6; //book specifies that the keyword is required
std::cout << i ;
}
int main()
{
A a;
Func(a);
return 0;
}
-
Re: C++ Templates: The Complete Guide
Comeau is OK with the OP's code if you move the int definition.
Code:
#include <iostream>
using namespace std;
// maximum of two int values
inline int const& max (int const& a, int const& b)
{
cout << "inline int const& max (int const& a, int const& b)" << endl;
return a < b ? b : a;
}
// maximum of two values of any type
template <typename T>
inline T const& max (T const& a, T const& b)
{
cout << "inline T const& max (T const& a, T const& b)" << endl;
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& max (T const& a, T const& b, T const& c)
{
cout << "inline T const& max (T const& a, T const& b, T const& c)" << endl;
return max (max(a,b), c); // uses the template version even for ints
} // because the following declaration comes
// too late:
int main()
{
int a, b, c;
a = 1; b = 2; c = 3;
max(a,b,c);
getchar();
return 0;
}
It's also happy if you move the int definition and change it to a specialised function template.
Code:
// maximum of two int values
template <>
inline int const& max<int>(int const& a, int const& b)
{
std::cout << "inline int const& max (int const& a, int const& b)" << std::endl;
return a < b ? b : a;
}
Though you must remove the using namespace std; otherwise the STL max definitions conflict.
-
Re: C++ Templates: The Complete Guide
Can anyone test what the above variations do under GCC?
Both variants give the output below, under VS2008.
inline T const& max (T const& a, T const& b, T const& c
inline int const& max (int const& a, int const& b)
inline int const& max (int const& a, int const& b)
Note: It's better to name the functions other than 'max' as this alleviates any possibility of compilation weirdness do to conflict with other 'max' definitions.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by JohnW@Wessex
Can anyone test what the above variations do under GCC?
Both variants give the output below, under VS2008.
inline T const& max (T const& a, T const& b, T const& c
inline int const& max (int const& a, int const& b)
inline int const& max (int const& a, int const& b)
I get the same output with the MinGW port of g++ 3.4.5.
Quote:
Originally Posted by JohnW@Wessex
Note: It's better to name the functions other than 'max' as this alleviates any possibility of compilation weirdness do to conflict with other 'max' definitions.
We could just fully qualify each use of max.
-
Re: C++ Templates: The Complete Guide
So what's the verdict on this?
With STL name clashes eliminated and function declarations slightly re-ordered, Comeau compiles OK and VS2008 & GCC agree on the functions that are actually executed.
Do we agree that this is compliant behaviour?
-
Re: C++ Templates: The Complete Guide
i think you're missing the point of my question. Reordering is not a solution, as i shouldnt need to re-order anything to follow along with the book. The problem is not being able to follow along with the examples and techniques as they are written.
I really dont know what to do about this. I could just work with the way VS does it, and it be non portable or i can change compiler. I dont think trying to write compliant code under VS is a viable option as its never going to tell me about the non compilant mistakes i happen to make along the way, and then when i do come to port it, i'll have to make appropiate fixes, or find subtle bugs.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
wheelie
i think you're missing the point of my question. Reordering is not a solution
I understand your original question, I just was curious as to whether the re-ordered code was valid or invalid too.
The re-ordered code makes the execution of the code identical in VS2008 and GCC where before in wasn't.
Pasting your original code into Comeau (generally believed to be the most compliant), after changing 'max' to 'maximum' to avoid name clashes with the STL, results in zero errors.
Code:
#include <iostream>
using namespace std;
// maximum of two values of any type
template <typename T>
inline T const& maximum (T const& a, T const& b)
{
cout << "inline T const& maximum (T const& a, T const& b)" << endl;
return a < b ? b : a;
}
// maximum of three values of any type
template <typename T>
inline T const& maximum (T const& a, T const& b, T const& c)
{
cout << "inline T const& maximum (T const& a, T const& b, T const& c)" << endl;
return maximum (maximum(a,b), c); // uses the template version even for ints
} // because the following declaration comes
// too late:
// maximum of two int values
inline int const& maximum (int const& a, int const& b)
{
cout << "inline int const& maximum (int const& a, int const& b)" << endl;
return a < b ? b : a;
}
int main()
{
int a, b, c;
a = 1; b = 2; c = 3;
maximum(a,b,c);
getchar();
return 0;
}
Quote:
In strict mode, with -tused, Compile succeeded
So the question is, who is correct?
The book or VS2008 / GCC / Comeau?
I don't know.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
wheelie
Reordering is not a solution, as i shouldnt need to re-order anything to follow along with the book. The problem is not being able to follow along with the examples and techniques as they are written.
Your doubt about the book started when you didn't follow the book properly,
and we cleared that part up for you.
Quote:
I could just work with the way VS does it, and it be non portable or i can change compiler.
What you bring to the discussion - the compliance discrepency among the compiler - is nothing new.
You should've known this when you were a beginner
Code:
#include <string>
int main()
{
std::string str("Cow");
str.erase(str.end());
}
not at the learning curve where you bought the book to "futher the understanding."
When Josuttis gave his example on type designation in templates,
did he mention the name of the compiler?
Did he say, "typename required on MSVS compiler?"
If not, why are you turning everything you found in his work on one particular compiler and judge his whole work?
Quote:
I really dont know what to do about this
You should draw your own conculsion
Few days passed and not a single word of educated opinions on your part as to what you think should happen. What gives!
Do you think non-template version should've been called? or the template version?
What are the arguments behind that choice?
EDIT:
So, let's share our educated opinion to reach some conclusion
I'll start first.
Q. In C++, which happens first? type checking or name look up?
-
Re: C++ Templates: The Complete Guide
Quote:
Your doubt about the book started when you didn't follow the book properly,
and we cleared that part up for you.
Where did you clear it up? If you're refering to your reply on the using namespace problem, i reposted the code without the using namespace and got the exact same result.
Quote:
If not, why are you turning everything you found in his work on one particular compiler and judge his whole work?
I thought id been quite clear on this, ..... Im not judging his work at all, im not saying he is wrong or anything like that, .. I'm simply wondering how to continue with the book, when Visual Studio is the compiler ive been using for so long.
Quote:
You should draw your own conculsion
Few days passed and not a single word of educated opinions on your part as to what you think should happen. What gives!
Do you think non-template version should've been called? or the template version?
What are the arguments behind that choice?
I think that the way Joshuttis explains makes the most sense, in that yes the non template functions should be called first, but they cant in this case because they havent been seen yet. The fact that it doesnt go this way in Visual Studio was the whole point of this thread.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
wheelie
I think that the way Joshuttis explains makes the most sense, in that yes the non template functions should be called first, but they cant in this case because they havent been seen yet.
Looking at the code, I expected that the integer version would be called because by the time the compiler parses 'main', which is the first place that 'max' is invoked, it has seen both the int and template definitions. Therefore the compiler would use the 'best fit', which would be the int version. So, from my reasoning, the Visual Studio execution of the code was perfectly logical.
My logic may not coincide with that of the C++ Standard creators. :rolleyes:
-
Re: C++ Templates: The Complete Guide
Hmm, i see what you're saying. But if i was to write
Code:
//void Func1();
void Func2()
{
Func1();
}
void Func1()
{
}
int main()
{
Func2();
return 0;
}
Its clearly an error, unless i uncomment out the declaration. And having it uncommented is the same as what you thought should logically compile. The way that VS is getting away with it, i assume is due to the double comiling that template compilation goes through.
Once for Syntax Check
Second time round for instantiation
So when VS compiles it, it also keeps track over the declarations its read, for the second pass.
I think GCC does the same, just doesnt remember the declarations from the first pass. So order is therefore important. Thats my thinking, not sure if its correct.
-
Re: C++ Templates: The Complete Guide
But there is a difference in that the your original example contains template definitions. The compiler doesn't actually have to generate any code until it finds a place where they are required. I've found errors in a couple of my templates, a long time after I wrote them, because I hadn't created any code that actually used them until then.
From what I can see, when the compiler parses max(a, b, c) it generates the code from the three parameter template with int as the type. As it generates the code, it finds a call to max with two int parameters and has the choice between the templated version or the 'int' version. The int version is the better match.
Whether that's how it should work is another matter, but it seems logical to me.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
JohnW@Wessex
Looking at the code, I expected that the integer version would be called because by the time the compiler parses 'main', which is the first place that 'max' is invoked, it has seen both the int and template definitions. Therefore the compiler would use the 'best fit', which would be the int version.
Yes, according to the lookup rules, the compiler will choose the non-templated version over the templated version.
Regards,
Paul McKenzie
-
Re: C++ Templates: The Complete Guide
Quote:
Looking at the code, I expected that the integer version would be called because by the time the compiler parses 'main', which is the first place that 'max' is invoked, it has seen both the int and template definitions
Yes, but i believe that problem is not whether main has seen the int version, but whether the max template further up has. Which is why is doesnt work with GCC.
max(a,b)
max(a,b,c)
max(int, int);
As Joshutis explains, becuase max(a,b,c) hasnt seen max(int,int), it can only use max(a,b). That is unless you use Visual studio.
Quote:
Yes, according to the lookup rules, the compiler will choose the non-templated version over the templated version.
Only if its been seen though, which in this case, it hasnt. max(a,b,c) has only seen max(a,b), so that is the only template or function it can use.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
JohnW@Wessex
So what's the verdict on this?
With STL name clashes eliminated and function declarations slightly re-ordered, Comeau compiles OK and VS2008 & GCC agree on the functions that are actually executed.
Do we agree that this is compliant behaviour?
If my vote counts, I think it is (for the one with template specialization)
Quote:
Originally Posted by wheelie
As Joshutis explains, becuase max(a,b,c) hasnt seen max(int,int), it can only use max(a,b). That is unless you use Visual studio.
I think the order in which the overloaded functions appear shouldn't really matter
becase of all the look up rules, and not to mention how it would be impractical to design such a set if it did.
So I'm all for Paul's first observation that anything can happen with a code such as the OP,
or, at best, overloading template and non template in this way is compiler dependant
since the responsibility of generating the right code lies on the compiler, not us.
so I'll say this again, prefer template specialization over it!
And a reputation for wheelie for recognizing this issue :thumb:
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
potatoCode
So I'm all for Paul's first observation that anything can happen with a code such as the OP,
or, at best, overloading template and non template in this way is compiler dependant
since the responsibility of generating the right code lies on the compiler, not us.
so I'll say this again, prefer template specialization over it!
And a reputation for wheelie for recognizing this issue :thumb:
Well the order doesnt seem to matter in Visiual Studio, but Joshuttis specifically mentions that the order does matter
Quote:
// uses the template version even for ints
// because the following declaration comes
// too late:
I think im going to play around with this some more, becuase if the order does matter, then that goes against one of herb sutters articles too.
http://www.gotw.ca/publications/mill17.htm
That is unless order *after* name lookup for finding more specialised functions matters. Gah ! its all getting very complicated :P :)
-
Re: C++ Templates: The Complete Guide
This seems to be a key point in the article.
Quote:
Originally Posted by Herb Sutter
Nontemplate functions are first-class citizens. A plain old nontemplate function that matches the parameter types as well as any function template will be selected over an otherwise-just-as-good function template.
-
Re: C++ Templates: The Complete Guide
The 3 functions in that article arent nontemplate functions. And again, im discussing order here, which i believe is the source of confusion.
If we had a strict rule about template ordering that all compilers were to obey by then the different results we have gotten here wouldnt have occurred.
From my understanding, GCC follows the rule, (that is also set in Joshutis's book), that templates have to be seen by the *calling template* before they can be called, otherwise, they're not taken into consideration.
From my experience:-
- GCC requires ordered template functions. In that a template has to have been seen by a *calling template* before another can call it. That is -
template Func A;
template Func B;
template Func C;
With regard to GCC, Func B only knows about, and can only call A
- Visual Studio does not require ordered template functions.
template Func A;
template Func B;
template Func C;
With regard to VS, Func B can call A and C.
Again, this is from my experience with codeblocks and VS. I dont know how compliant GCC is, but its what ive come to understand.
-
Re: C++ Templates: The Complete Guide
Quote:
Originally Posted by
wheelie
The 3 functions in that article arent nontemplate functions.
In Example 1, function (f) is a non-template function.
Code:
// A function template with two overloads
template<class T> void f( T ); // (b)
template<class T> void f( int, T, double ); // (c)
// A separate base template that overloads (b) and (c)
// -- NOT a partial specialization of (b), because
// there's no such thing as a partial specialization
// of a function template!
template<class T> void f( T* ); // (d)
// A full specialization of (b) for int
template<> void f<int>( int ); // (e)
// A plain old function that happens to overload with
// (b), (c), and (d) -- but not (e), which we'll
// discuss in a moment
void f( double ); // (f)
-
Re: C++ Templates: The Complete Guide
:P
well ok, but i was meaning the main chunk of the article rather than the introductory stuff, under the title
Why Not Specialize: The Dimov/Abrahams Example