What are those _Traits for?

V

Vince C.

Hi all.

I can see the standard template library has changed a lot since I begun C++
10 years ago...

Now I'm facing with outputing the members of a struct, say Option, which
contains 2 members through ostream. I have defined a vector of Option:

struct Option {
char* name;
int value;
};

typedef vector<Option> ovect;

....

int main()
{
ovect v();
ovect.reserve(10);
...
// Add elements to the vector
cout << v[0];
...
return 0;
}

When I compile (in Bloodshed Dev-C++) I get zillions of errors like:

main.cpp:85: error: no match for 'operator<<' in 'std::eek:perator<< [with
_Traits = std::char_traits<char>](((std::basic_ostream<char,
std::char_traits said:
&)(&std::cout)), std::setw(4)))->std::basic_ostream<_CharT,
_Traits>::eek:perator<< [with _CharT = char, _Traits = std::char_traits<char>
(i))), ((const char*)" ")) << ((const std::vector<gnu_opt,
std::allocator<gnu_opt> >*)(+v))->std::vector<_Tp, _Alloc>::eek:perator[]
[with _Tp = gnu_opt, _Alloc = std::allocator<gnu_opt>](i)'

C:/dev/Dev-Cpp/Bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/ostream.tcc:63:
note: candidates are: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(std::basic_ostream<_CharT,
_Traits>&(*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char,
_Traits = std::char_traits<char>]
....
C:/dev/Dev-Cpp/Bin/../lib/gcc/mingw32/3.4.2/../../../../include/c++/3.4.2/bits/ostream.tcc:74:
note: std::basic_ostream<_CharT, _Traits>&
std::basic_ostream<_CharT, _Traits>::eek:perator<<(std::basic_ios<_CharT,
_Traits>&(*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char,
_Traits = std::char_traits<char>]

I've digged into the iostream library and I must admit there is nothing like
I used to know about that library before, everything has changed :( .
Especially I can't figure out what the typename _Traits is for in standard
template library templates. I can see _Traits in strings, ostreams,
istreams, aso.

I guess I need to create an operator "<<" for my structure but I have no
idea of what it should look like.

Thanks for any hint/suggestion.
 
K

Kai-Uwe Bux

Vince said:
Hi all.

I can see the standard template library has changed a lot since I begun
C++ 10 years ago...

Now I'm facing with outputing the members of a struct, say Option, which
contains 2 members through ostream. I have defined a vector of Option:

struct Option {
char* name;
int value;
};

typedef vector<Option> ovect;

...

int main()
{
ovect v();

That does not declare a vector but a function.
ovect.reserve(10);
v.reserve(10);

...
// Add elements to the vector
cout << v[0];
...
return 0;
}

When I compile (in Bloodshed Dev-C++) I get zillions of errors like: [snip]
I've digged into the iostream library and I must admit there is nothing
like I used to know about that library before, everything has changed :( .
Especially I can't figure out what the typename _Traits is for in standard
template library templates. I can see _Traits in strings, ostreams,
istreams, aso.

I guess I need to create an operator "<<" for my structure but I have no
idea of what it should look like.


Try something like this:

#include <iostream>
#include <ostream>
#include <vector>

struct Option {
char* name;
int value;
};

std::eek:stream & operator<< ( std::eek:stream & ostr,
Option const & opt ) {
ostr << opt.name << " : " << opt.value;
return ( ostr );
}


typedef std::vector<Option> ovect;


int main()
{
ovect v;
v.reserve(10);
Option opt;
opt.value = 1;
opt.name = "name";
v.push_back( opt );
std::cout << v[0] << '\n';
}

BTW: you should consider using std::string instead of char*.


Best

Kai-Uwe Bux
 
V

Vince C.

Kai-Uwe Bux said:
Vince C. wrote: ....
Kai-Uwe Bux

Thanks a lot. In fact I made an error while defininig operator <<, which
second argument was not Option const but vector<Option>... That could not
work, of course. Now it does.

Thanks again for your help.

Note I still don't know what the _Traits are for in templates... What is
their purpose? (Just out of curiosity.)
 
K

Kai-Uwe Bux

Vince said:
Thanks a lot. In fact I made an error while defininig operator <<, which
second argument was not Option const but vector<Option>... That could not
work, of course. Now it does.

Thanks again for your help.

Note I still don't know what the _Traits are for in templates... What is
their purpose? (Just out of curiosity.)

Generally, traits classes carry information about types. For instance
std::string is defined as

typedef std::basic_string<char> string;

and the template basic_string reads like:

template < typename CharT,
typename Traits=char_traits<CharT>,
typename Alloc=allocator<CharT> >
class basic_string;

Now, the CharT is the underlying type for the characters in the string.
Usually, that would be char, unsigned char or something like wchar_t. Some
operations are not hard-coded into the basic_string template, instead they
are parameterized. For instance all memory allocation and deallocation is
done through Alloc.

The Traits parameter, in this case, provides a hook for the user to tell
basic_string which C-string functions to use. The basic_string<> template
will assume that Traits names a class type the provides some static
functions, such as

Traits::length( CharT const * ); // may use strlen()
Traits::eq( CharT lhs, CharT rhs ); // may use ==
Traits::lt( CharT lhs, CharT rhs ); // may use <

Now, Traits::eq() will be called whenever basic_string needs to determine
whether two values of type CharT are equal. Similarly, Traits::length()
will be called whenever basic_string needs to determine the length of a
C-style string. E.g., the constructor from a C-string might be implemented
like this:

basic_string ( CharT const * cstr,
Alloc const & a = Alloc() )
: container ( cstr, cstr + Traits::length( cstr ), a )
{
container.push_back( charT() ); // add a 0
}

You could use the Traits parameter to write a case-insensite string class
(which is probably not the best idea). More importantly (for basic_string),
this allows basic_string to call fast implementation (e.g., of strlen)
depending on the particular CharT. Thus, with basic_string, it is also a
trick to boost performance.


Another example are iterator_traits<>. The standard knows certain kinds of
iterators that have different abilities. The standard algorithms are just
fed some iterators. It is easy to provide a generic implementation for,
say,

template < typename InIter, typename OutIter >
OutIter copy ( InIter from, InIter to, OutIter where );

However, if InIter is a random access iterator and OutIter is a
back_inserter for a vector, one could envision a performance improvement by
first computing the number of objects to be copied and doing a call to
reserve. Using

iterator_traits<InIter>

and

iterator_traits<OutIter>

you could, with a little bit of template magic, provide a specialized
version of copy() that is better for the particular situation.



Best

Kai-Uwe Bux
 
J

James Kanze

Thanks a lot. In fact I made an error while defininig operator <<, which
second argument was not Option const but vector<Option>... That could not
work, of course. Now it does.
Thanks again for your help.
Note I still don't know what the _Traits are for in templates... What is
their purpose? (Just out of curiosity.)

In the case of iostream, to add complexity, and make
implementation more difficult. They're not very useful
otherwise.

In general, the concept of traits can be used to provide complex
additional information to a template, with default values.
 
V

Vince C.

Kai-Uwe Bux said:
Generally, traits classes carry information about types. [...]

Now, the CharT is the underlying type for the characters in the string.
Usually, that would be char, unsigned char or something like wchar_t. Some
operations are not hard-coded into the basic_string template, instead they
are parameterized. For instance all memory allocation and deallocation is
done through Alloc.

The Traits parameter, in this case, provides a hook for the user to tell
basic_string which C-string functions to use. [...]

Kai-Uwe Bux

Thanks a lot for that information, Kai-Uwe. That seems much clearer now.

To check if I understood, you need Traits whenever you need to optimize
operations provided by the basic class, according to the item type of a
vector, for instance?

In the string example you gave, there could be Traits for wide strings that
use the wide char version of string functions, is that correct? While there
would be Traits for char* that use the single byte functions, am I still
in? This allows for writing template member functions that optimize the
code according to the type, correct?

If I have understood, Traits have the benefical effect of not to rewrite the
whole template if the type changes *and* the way items are handled (copy,
compare, length, aso) but only the set of basic operations the base
template needs. Do I still follow?

So if I want a vector which elements are structures, I'd be better off
writing a Traits for that structure, too, wouldn't I?
 
B

BobR

Vince C. said:
So if I want a vector which elements are structures, I'd be better off
writing a Traits for that structure, too, wouldn't I?

The compiler usually does a good job passing that information to the
(std::)templates. You only need to pass 'Traits' in special circumstances.

I've stuffed some pretty hairy class/struct things in std::vector, and never
had to do a 'Traits' on them (....yet, knock-on-wood. <G>).

Don't worry about it until you actually need to (other than a learning
thing, of course.).


"Thinking in C++", vol 2, might interest you (templates, std:: lib, etc.).
Get "Thinking in C++", 2nd ed. Volume 1&2 by Bruce Eckel
(available for free here. You can buy it in hardcopy too.):
http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html

The Dinkumware site has some good documentation:
http://www.dinkumware.com/manuals/.

Josuttis's book is often suggested:
http://www.josuttis.com/libbook/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top