This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Curious issue with char_traits


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]