This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Curious issue with char_traits
- From: Howard Hinnant <hhinnant at apple dot com>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Tue, 25 Oct 2005 11:10:30 -0400
- Subject: Re: Curious issue with char_traits
- References: <435E304A.1000504@suse.de>
On Oct 25, 2005, at 9:16 AM, Paolo Carlini wrote:
Hi,
while answering privately a message from a user, I noticed a curious
glitch. Consider this:
--------
#include <string>
using namespace __gnu_cxx;
using namespace std;
typedef basic_string<char, char_traits<char>, allocator<char> > mystr;
--------
Well, doesn't compile!
plain.cc:6: error: 'char_traits' was not declared in this scope
plain.cc:6: error: missing '>' to terminate the template argument list
plain.cc:6: error: template argument 2 is invalid
plain.cc:6: error: expected unqualified-id before '>' token
The problem is that our "extended" char_traits implementation
involves a
template struct named char_traits *both* in __gnu_cxx and in std
(which
uses the former). But __gnu_cxx is the namespace where all our
extension
facilities live and as soon as a user does 'using namespace
__gnu_cxx;'
(I think it can be common), then char_traits becomes ambiguous (an
additional std:: qualifier becomes necessary)
I think we should fix this, i.e., we should render std::char_traits
robust wrt using-directives. What about renaming
__gnu_cxx::char_traits
to something like __gnu_cxx::__char_traits? This would fix the problem
at issue and it would still be possible to specialize
__gnu_cxx::__char_traits.
Opinions?
I think that would help. However there are a couple of more gotchas
if we intend on char_traits<some scalar other than char and wchar_t>
to be robust. Consider:
#include <string>
#include <ext/algorithm>
template <class T> void copy_n(T, long, int);
int main()
{
copy_n(std::char_traits<unsigned char>(), 0, 0);
}
Now, no using statements are involved. But the contents of __gnu_cxx
is still polluting the namespace. Because of an implementation
detail of std::char_traits (it derives from something in __gnu_cxx),
__gnu_cxx is searched when making an unqualified call with
std::char_traits as a parameter. Here is perhaps a more insidious
example of the same problem:
#include <string>
#include <ext/algorithm>
template <class T> void copy_n(T, long, int);
int main()
{
copy_n(std::basic_string<unsigned char>(), 0, 0);
}
We still get pollution from __gnu_cxx because
std::char_traits<unsigned char> is associated with
std::basic_string<unsigned char>.
In general it is dangerous to derive from anything in __gnu_cxx, even
as an implementation detail, unless __gnu_cxx contains nothing but
__xxx (or _X) identifiers.
-Howard