Topic: Const problem when instantiating function template
Author: tom_usenet@hotmail.com (tom_usenet)
Date: Fri, 21 May 2004 04:57:54 +0000 (UTC) Raw View
On Mon, 17 May 2004 17:18:12 +0000 (UTC), stefan_heinzmann@yahoo.com
(Stefan Heinzmann) wrote:
>Hi all,
>
>I have disagreement between two compilers when deducing template
>parameters on instantiation of a function template and would like to
>know which compiler is right. The problem is related to a const
>qualification. Here's the code:
[SNIP]
Here's simplified version:
template <class T>
void f(T const& t);
int main()
{
int const array[1] = {0};
f(array);
//What shoud T be deduced as in the call to f?
}
Well, during TAD (template argument deduction), P is the parameter
type (const T&) and A is the argument type (int const[1]). A is not
transformed since P is a reference type, but P is transformed to "T
const" (the referenced type is used, see 14.8.2.1/2).
So, we need to choose a T such that T const == int const[1]. Now, both
T = int const[1] and T = int[1] make the above true, since const
qualifying an array is equivalent to const qualifying the elements.
Comeau and VC 7.1 deduce T = int const[1] and GCC 3.3 deduces T =
int[1]. I really can't see anything in the standard to say which is
right, so perhaps this is a defect in the standard. Defect report
anyone?
Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: stefan_heinzmann@yahoo.com (Stefan Heinzmann)
Date: Mon, 17 May 2004 17:18:12 +0000 (UTC) Raw View
Hi all,
I have disagreement between two compilers when deducing template
parameters on instantiation of a function template and would like to
know which compiler is right. The problem is related to a const
qualification. Here's the code:
#include <algorithm>
// =============================================================
// Generic map element declarations.
// -------------------------------------------------------------
template<typename Elem> struct map_element_traits;
template<typename Elem> inline
const typename map_element_traits<Elem>::key_type&
key(const Elem& element)
{
return map_element_traits<Elem>::key(element);
}
template<typename Elem> inline
const typename map_element_traits<Elem>::mapped_type&
mapped_value(const Elem& element)
{
return map_element_traits<Elem>::mapped_value(element);
}
template<typename Elem>
struct key_value_compare
{
typedef typename map_element_traits<Elem>::value_type vtype;
bool operator()(const vtype& a, const vtype& b) const
{
return map_element_traits<Elem>::key(a)
< map_element_traits<Elem>::key(b);
}
};
// =============================================================
// Generic map declarations.
// -------------------------------------------------------------
template<typename Map> struct map_traits;
template<typename Map> inline
typename map_traits<Map>::const_iterator
begin(Map const& map)
{
return map_traits<Map>::begin(map);
}
template<typename Map> inline
typename map_traits<Map>::const_iterator
end(Map const& map)
{
return map_traits<Map>::end(map);
}
template<typename Map> inline
typename map_traits<Map>::const_iterator
find(Map const& m, typename map_traits<Map>::key_type const& k)
{
return map_traits<Map>::find(m, k);
}
template<typename Map>
typename map_traits<Map>::mapped_type const&
lookup( Map const& map,
typename map_traits<Map>::key_type const& key,
typename map_traits<Map>::mapped_type const& def_value)
{
typename map_traits<Map>::const_iterator i = find(map, key);
return (i == end(map)) ? def_value : mapped_value(*i);
}
// =============================================================
// Types for lookup tables stored in ROM.
// -------------------------------------------------------------
template<typename Key, typename Val>
struct Pair
{
Key key;
Val val;
};
template<typename Key, typename Val>
struct map_element_traits< Pair<Key,Val> >
{
typedef Pair<Key,Val> value_type;
typedef Key key_type;
typedef Val mapped_type;
static const key_type& key(const value_type& e)
{ return e.key; }
static const mapped_type& mapped_value(const value_type& e)
{ return e.val; }
};
template<typename Key, typename Val, unsigned n>
struct map_traits< Pair<Key,Val>[n] > //### const or not?
{
typedef Key key_type;
typedef Val mapped_type;
typedef Pair<Key,Val> value_type;
typedef const value_type* const_iterator;
static const_iterator begin(const value_type (&map)[n])
{ return &map[0]; }
static const_iterator end (const value_type (&map)[n])
{ return &map[n]; }
static const_iterator find(const value_type (&map)[n]
,const key_type& k)
{
value_type elem = { k };
const_iterator i = std::lower_bound(begin(map), end(map)
, elem, key_value_compare<value_type>());
return (i == end(map) || key(*i) != k) ? end(map) : i;
}
};
// =============================================================
// Usage test
// -------------------------------------------------------------
const Pair<int, const char*> table[] =
{
{ 0, "Ok" },
{ 6, "Minor glitch in self-destruction module" },
{ 13, "Error logging printer out of paper" },
{ 101, "Emergency cooling system inoperable" },
{ 2349, "Dangerous substances released" },
{ 32767, "Game over, you lost" }
};
int main()
{
const char *result = lookup(table, 5, "not found");
}
The problem is related to the struct map_traits. GCC 3.3 compiles the
code as shown, whereas VC++ 7.1 needs the marked line to be changed to this:
struct map_traits< const Pair<Key,Val>[n] > //### const or not?
Obviously, the two compilers disagree when deducing the type of the
first argument to the lookup function template. Which one is right?
--
Cheers
Stefan
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]