|  | std::max(unsigned, size_t), amd64 and C++0x |  | |
| | | Alex Shulgin |  |
| Posted: Wed Aug 27, 2008 6:04 am Post subject: std::max(unsigned, size_t), amd64 and C++0x |  |
| |  | |
Hi,
This definitely should have been asked before, but now I just cannot seem to find the related topic.
unsigned i = 1; size_t j = 2; std::cout << std::max(i, j);
This code compiles w/o a problem on i386 (tried g++ 4.1.2 and Comeau online), but fails to compile on amd64 platform. g++ reports:
error: no matching function for call to ‘max(unsigned int&, size_t&)’
The problem, I believe, is that std::max is declared like
template< typename T > T max(T a, T b) { ... }
and that `unsigned' and `size_t' are actually different types with g++ on amd64, but are the same on i386.
In order to support different arbitrary types in std::max() arguments we would need some magic template like this:
template< typename T, typename U > typename wider_type< T, U >::type max(T t, U u) { ... }
and this is barely possible w/o writing down by hand all the needed specializations for wider_type<>.
To me this is a reminiscent of some classical problem with C++ templates I cannot recall correctly now... ;)
Is C++0x's `auto' supposed to handle this sort of things?
-- Cheers, Alex Shulgin
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Nick Hounsome |  |
| Posted: Thu Aug 28, 2008 8:14 am Post subject: Re: std::max(unsigned, size_t), amd64 and C++0x |  |
| |  | |
On 27 Aug, 07:04, Alex Shulgin <alex.shul...@gmail.com> wrote:
| Quote: | Hi,
This definitely should have been asked before, but now I just cannot seem to find the related topic.
unsigned i = 1; size_t j = 2; std::cout << std::max(i, j);
This code compiles w/o a problem on i386 (tried g++ 4.1.2 and Comeau online), but fails to compile on amd64 platform. g++ reports:
error: no matching function for call to ‘max(unsigned int&, size_t&)’
The problem, I believe, is that std::max is declared like
template< typename T > T max(T a, T b) { ... }
and that `unsigned' and `size_t' are actually different types with g++ on amd64, but are the same on i386.
In order to support different arbitrary types in std::max() arguments we would need some magic template like this:
template< typename T, typename U typename wider_type< T, U >::type max(T t, U u) { ... }
and this is barely possible w/o writing down by hand all the needed specializations for wider_type<>.
To me this is a reminiscent of some classical problem with C++ templates I cannot recall correctly now... ;)
Is C++0x's `auto' supposed to handle this sort of things?
-- Cheers, Alex Shulgin
|
Firstly auto wont do anything at all for this. decltype would be more use since it would allow you to make j the same type as i.
Secondly I read somewhere recently a rant about the STL implementation of max and why it was so complicated - It appears that for such an intuitively simple function, max is actually extremely difficult, if not impossible to get right in all cases.
Thirdly IMHO size_t should have been made a distinct type like wchar_t because: 1) You could then overload on it. 2) You wouldn't get this sort of error message on some platforms and not others - it would be an error everywhere.
And finally the solution is to make i a size_t or static cast it to size_t in the call since size_t is never going to be smaller than unsigned int.
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Marco Manfredini |  |
| Posted: Thu Aug 28, 2008 8:20 am Post subject: Re: std::max(unsigned, size_t), amd64 and C++0x |  |
Alex Shulgin wrote:
| Quote: | unsigned i = 1; size_t j = 2; std::cout << std::max(i, j);
This code compiles w/o a problem on i386 (tried g++ 4.1.2 and Comeau online), but fails to compile on amd64 platform. g++ reports:
error: no matching function for call to ?max(unsigned int&, size_t&)?
The problem, I believe, is that std::max is declared like
template< typename T > T max(T a, T b) { ... }
|
It's more like the problem that max is declared: template< typename T > const T& max(const T& a, const T &b) { ... }
Which makes the wider_type<> attempt somewhat infeasible.
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | peter koch larsen |  |
| Posted: Thu Aug 28, 2008 8:21 am Post subject: Re: std::max(unsigned, size_t), amd64 and C++0x |  |
| |  | |
On 27 Aug., 08:04, Alex Shulgin <alex.shul...@gmail.com> wrote:
| Quote: | Hi,
This definitely should have been asked before, but now I just cannot seem to find the related topic.
unsigned i = 1; size_t j = 2; std::cout << std::max(i, j);
This code compiles w/o a problem on i386 (tried g++ 4.1.2 and Comeau online), but fails to compile on amd64 platform. g++ reports:
error: no matching function for call to ‘max(unsigned int&, size_t&)’
The problem, I believe, is that std::max is declared like
template< typename T > T max(T a, T b) { ... }
and that `unsigned' and `size_t' are actually different types with g++ on amd64, but are the same on i386.
|
Right. So this is not really a problem with the std::max template, but rather with your code that mixes up two different types. Correct the problem by having a consistent use of types.
| Quote: | In order to support different arbitrary types in std::max() arguments we would need some magic template like this:
template< typename T, typename U typename wider_type< T, U >::type max(T t, U u) { ... }
and this is barely possible w/o writing down by hand all the needed specializations for wider_type<>.
|
I have seen "better" definitions of max, but they are rather complex and IMHO not worth the trouble. Normally the arguments to std::max should have the same type, and in the rare case where they do not, it is better to explicitly qualify max as in e.g. std::max<size_t>(a,b).
/Peter
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Alberto Ganesh Barbati |  |
| Posted: Thu Aug 28, 2008 8:58 am Post subject: Re: std::max(unsigned, size_t), amd64 and C++0x |  |
| |  | |
Alex Shulgin ha scritto:
| Quote: | Hi,
This definitely should have been asked before, but now I just cannot seem to find the related topic.
unsigned i = 1; size_t j = 2; std::cout << std::max(i, j);
This code compiles w/o a problem on i386 (tried g++ 4.1.2 and Comeau online), but fails to compile on amd64 platform. g++ reports:
error: no matching function for call to ‘max(unsigned int&, size_t&)’
The problem, I believe, is that std::max is declared like
template< typename T > T max(T a, T b) { ... }
and that `unsigned' and `size_t' are actually different types with g++ on amd64, but are the same on i386.
In order to support different arbitrary types in std::max() arguments we would need some magic template like this:
template< typename T, typename U typename wider_type< T, U >::type max(T t, U u) { ... }
and this is barely possible w/o writing down by hand all the needed specializations for wider_type<>.
|
This should be a job for the new common_type<> template introduced in the latest draft of C++0x. Alas, the current wording of common_type<> would produce the wrong result in the mixed-sign case max(-1, 1u). This is my first and strongest objection to the current wording of common_type<> but my alternative proposal received a very cold feedback.
| Quote: | To me this is a reminiscent of some classical problem with C++ templates I cannot recall correctly now... 
|
Actually, this is a safety feature...
| Quote: | Is C++0x's `auto' supposed to handle this sort of things?
|
Unfortunately, no: auto won't help in this case.
Ganesh
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Erik Wikström |  |
| Posted: Thu Aug 28, 2008 8:32 pm Post subject: Re: std::max(unsigned, size_t), amd64 and C++0x |  |
| |  | |
On 2008-08-27 08:04, Alex Shulgin wrote:
| Quote: | Hi,
This definitely should have been asked before, but now I just cannot seem to find the related topic.
unsigned i = 1; size_t j = 2; std::cout << std::max(i, j);
This code compiles w/o a problem on i386 (tried g++ 4.1.2 and Comeau online), but fails to compile on amd64 platform. g++ reports:
error: no matching function for call to ‘max(unsigned int&, size_t&)’
The problem, I believe, is that std::max is declared like
template< typename T > T max(T a, T b) { ... }
and that `unsigned' and `size_t' are actually different types with g++ on amd64, but are the same on i386.
In order to support different arbitrary types in std::max() arguments we would need some magic template like this:
template< typename T, typename U typename wider_type< T, U >::type max(T t, U u) { ... }
and this is barely possible w/o writing down by hand all the needed specializations for wider_type<>.
To me this is a reminiscent of some classical problem with C++ templates I cannot recall correctly now... ;)
Is C++0x's `auto' supposed to handle this sort of things?
|
No, auto will only save you from typing the whole typename when it can be deducted from the expression (in this case from the function declaration). What might help in this case is decltype.
-- Erik Wikström
[ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | gpderetta |  |
| Posted: Thu Aug 28, 2008 8:35 pm Post subject: Re: std::max(unsigned, size_t), amd64 and C++0x |  |
| |  | |
On Aug 27, 8:04 am, Alex Shulgin <alex.shul...@gmail.com> wrote:
| Quote: | Hi,
This definitely should have been asked before, but now I just cannot seem to find the related topic.
unsigned i = 1; size_t j = 2; std::cout << std::max(i, j);
This code compiles w/o a problem on i386 (tried g++ 4.1.2 and Comeau online), but fails to compile on amd64 platform. g++ reports:
error: no matching function for call to ‘max(unsigned int&, size_t&)’
The problem, I believe, is that std::max is declared like
template< typename T > T max(T a, T b) { ... }
and that `unsigned' and `size_t' are actually different types with g++ on amd64, but are the same on i386.
|
An easy solution is to explicitly name the template parameter:
max<size_t>(i,j)
<snip>
| Quote: | Is C++0x's `auto' supposed to handle this sort of things?
|
I do not think it will help.
Min/max definition will likely change in C++0x, but I do not remember if this case is handled diferently.
HTH,
-- gpd
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Panhinda |  |
| Posted: Thu Aug 28, 2008 8:52 pm Post subject: Re: std::max(unsigned, size_t), amd64 and C++0x |  |
| Quote: | unsigned i = 1; size_t j = 2; std::cout << std::max(i, j);
|
The prototype says both parameters must be of same type. This code violates the prototype - hence the compile error. You should do something along the lines of -
unsigned i = 1; size_t j = 2; std::cout << std::max<size_t>(i, static_cast<size_t>(i));
This will compile on any platform.
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | SG |  |
| Posted: Thu Aug 28, 2008 9:58 pm Post subject: Re: std::max(unsigned, size_t), amd64 and C++0x |  |
On 27 Aug., 08:04, Alex Shulgin <alex.shul...@gmail.com> wrote:
| Quote: | template< typename T > T max(T a, T b) { ... }
and that `unsigned' and `size_t' are actually different types with g++ on amd64, but are the same on i386.
|
Implicit convertibility of types is not considered during template parameter deduction. But you can help the compiler choose the "right" template parameter:
unsigned a = get_a(); size_t b = get_b(); size_t max = std::max<size_t>(a,b);
Explicit conversion will also work:
size_t max = std::max(size_t(a),b);
Though, I'm not sure whether it's safe to assume that sizeof(unsigned) <= sizeof(size_t). To be on the safe side you may want to use some metaprogramming tricks a la decltype(a+b) for the right type.
Cheers, SG
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Pete Becker |  |
| Posted: Thu Aug 28, 2008 9:58 pm Post subject: Re: std::max(unsigned, size_t), amd64 and C++0x |  |
On 2008-08-27 22:14:08 -0400, Nick Hounsome <nick.hounsome@googlemail.com> said:
| Quote: | Secondly I read somewhere recently a rant about the STL implementation of max and why it was so complicated - It appears that for such an intuitively simple function, max is actually extremely difficult, if not impossible to get right in all cases.
|
The implementation of max is not complicated at all:
template <class T> T max(const T& t1, const T& t2) { return t1 < t2 ? t2 : t2; }
Maybe you're thinking of a proposal to add a bunch of stuff to max that bloated it to over 200 lines of code in order to "improve" it.
-- Pete Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The Standard C++ Library Extensions: a Tutorial and Reference (www.petebecker.com/tr1book)
[ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
|
|