RE: [boost] Re: Numeric conversions lib comments

In most part proposed design looks reasonable. I have only one major IMO concern.
Issue: (Major) Why traits are template parameter of converter? I've expressed my opinion in the matter before: Traits - as name suggest could not be policy. IOW should not be template parameters. Traits are type specific and an ability to supply them independently to the primary type in most cases leads to invalid/too complicated design. Traits are not only template parameters of public converter class but many other classes. IMO all of them should use S and T as template parameters instead.
I have to disagree. Traits are used as policies in too many designs, including the STL itself, and I don't see a problem with that. I agree
I don't say I like it either. Major issue with basic_string design IMO is that char_traits is template parameter
that traits classes are type specific, but they are used as policies precisely because of that: if the user of a parametrized facility wants a different treatment for a given type, she can't change *the* traits for the type, all she can do is pass in a different traits as a policy.
Here is how I see it. Trait is something type specific, IOW specific to type, IOW uniquely defined by type. If you could provide trait along with the type as a template parameter, that mean you could change it independently from the type, IOW you could define different value for trait still using the same type. For example if you have component C defined like: template<typename T, typename Trait> struct C { ... }; You could instantiate it like C<MyT,TraitValue1> or C<MyT,TraitValue2>. So as you could see trait value is not uniquely defined by the type. Proper design would be to have trait stand alone class, like this: template<typename T> struct Trait { value = ... }; template<typename T> struct C { here we are using Trait<T>::value, where we used to use Trait. }; Now if the user needs to define trait value (or change from using default value provided by most traits designs), she just need to define explicit/partial specialization for this type or types family. On the other hand policy is something that is orthogonal to the primary type (actually in policy based design there may not be any primary type, but just an orthogonal policies), IOW you could use different policies in conjunction with the same type. And natural place for the policy is along with type in component definition among the template parameters.
If this were not a policy, users would be stuck with the definition of the default traits class. I agree that this opens a window to all sort of problems in case a user plugs in an invalid traits, but I think that should not constitute a reason for fixing the traits into the converter. As always, "trust the programmer"
So again Trait is not a Policy and let's not mix them
4. converter<>::convert converts only rvalue. Why? IMO we need second operation that works with lvalues. What if I want to convert int& into char&? This requires the target lvalue as a parameter instead of a return value. It could be done yes, but I don't see the reason. Why would want to do that?
For example for [de]serialization solutions. What is in your opinion is problem domain for numeric conversion? Gennadiy.

"Rozental, Gennadiy" <gennadiy.rozental@thomson.com> wrote in message news:35C251B635189944B65CAB923470EA9601FEC600@execmail.apps.ilx.com...
I don't say I like it either. Major issue with basic_string design
IMO is
that char_traits is template parameter
<snip>
Here is how I see it. Trait is something type specific, IOW specific to type, IOW uniquely defined by type. If you could provide trait along with the type as a template parameter, that mean you could change it independently from the type, IOW you could define different value for trait still using the same type. For example if you have component C defined like:
On the other hand policy is something that is orthogonal to the
<snip> primary type
(actually in policy based design there may not be any primary type, but just an orthogonal policies), IOW you could use different policies in conjunction with the same type. And natural place for the policy is along with type in component definition among the template parameters.
This is probably the best characterization of the traits/policy distinction I've heard. I don't agree entirely about basic_string, however; I think that the comparison functions such as char_traits::compare have to be made available through template parameters, otherwise you wouldn't be able to reuse basic_string if you want strings with different comparison criteria. Most of the stuff in char_traits, such as the typedefs, copy, move, to_int_type, eof could go in a genuine traits template, so that basic_string would look like this: template<typename Ch, typename Comp = std::char_compare<Ch> > class basic_string; This wouldn't make a practical difference for strings, but it might mean that iostreams wouldn't need traits parameters at all -- I haven't verified this -- which would be a huge advantage. Jonathan

Jonathan Turkanis wrote:
This is probably the best characterization of the traits/policy distinction I've heard. I don't agree entirely about basic_string, however; I think that the comparison functions such as char_traits::compare have to be made available through template parameters, otherwise you wouldn't be able to reuse basic_string if you want strings with different comparison criteria.
I thought it was already common knowledge that the idea of using the 'char_traits' policy parameter of basic_string to override comparisons is inherently flawed. Usually the kind of comparison you want depends on the context where the string is used, not on the type of the string.

"Peter Dimov" <pdimov@mmltd.net> wrote in message news:003501c41363$d23fe7b0$1d00a8c0@pdimov2...
Jonathan Turkanis wrote:
This is probably the best characterization of the traits/policy distinction I've heard. I don't agree entirely about basic_string, however; I think that the comparison functions such as char_traits::compare have to be made available through template parameters, otherwise you wouldn't be able to reuse basic_string
if
you want strings with different comparison criteria.
I thought it was already common knowledge that the idea of using the 'char_traits' policy parameter of basic_string to override comparisons is inherently flawed. Usually the kind of comparison you want depends on the context where the string is used, not on the type of the string.
Yes, I know this argument, and in fact I have always used a comparison predicate when I need to customize string comparisons. However, if you accept that comparisons criteria are alway contextual, I think you must conclude that the comparison operators <, <=, etc. are completely useless. On the contrary, I like the ability to have a default comparison criteria that works a good deal of the time; as long as it's provided, it should be customizable. Jonathan

Jonathan Turkanis wrote:
However, if you accept that comparisons criteria are alway contextual, I think you must conclude that the comparison operators <, <=, etc. are completely useless. On the contrary, I like the ability to have a default comparison criteria that works a good deal of the time;
Agree.
as long as it's provided, it should be customizable.
Disagree. Your own logic doesn't support this conclusion: a default comparison works most of the time, therefore, it doesn't need to be customizable, because you could only customize it to _not work_ most of the time. And for the string case, the downside to encoding a comparison in the type is that you'll now spend a lot of time converting strings (because most libraries - correctly - accept an ordinary std::string, regardless of what comparisons they might make underneath, or they'd expose implementation details in the interface.) Nobody uses anything but std::string and std::wstring. ;-)

"Peter Dimov" <pdimov@mmltd.net> wrote in message news:004101c41369$2ca8cb90$1d00a8c0@pdimov2...
Jonathan Turkanis wrote:
However, if you accept that comparisons criteria are alway
contextual,
I think you must conclude that the comparison operators <, <=, etc. are completely useless. On the contrary, I like the ability to have a default comparison criteria that works a good deal of the time;
Agree.
as long as it's provided, it should be customizable.
Disagree. Your own logic doesn't support this conclusion: a default comparison works most of the time, therefore, it doesn't need to be customizable, because you could only customize it to _not work_ most of the time.
And for the string case, the downside to encoding a comparison in
Here's what I had in mind: for a particular application you might find that 'most of the time' you need a non-standard comparison criterion. It might make sense to let it be the default, so you can use the much cleaner operator notation. the type
is that you'll now spend a lot of time converting strings (because most libraries - correctly - accept an ordinary std::string, regardless of what comparisons they might make underneath, or they'd expose implementation details in the interface.)
You can expose the string as a typedef, to avoid bothering library users with custom comparison policies. Most of the interoperability concerns could be addressed by relaxing the requirement that traits_type match extacly in basic_string member functions which take basic_strings as arguments -- at least for those which don't involve comparison.
Nobody uses anything but std::string and std::wstring. ;-)
I've been waiting to meet the 'japan_char' I've read so much about; still haven't seen it. ;-) Jonathan

Jonathan Turkanis wrote:
"Peter Dimov" <pdimov@mmltd.net> wrote in message news:004101c41369$2ca8cb90$1d00a8c0@pdimov2...
And for the string case, the downside to encoding a comparison in the type is that you'll now spend a lot of time converting strings (because most libraries - correctly - accept an ordinary std::string, regardless of what comparisons they might make underneath, or they'd expose implementation details in the interface.)
You can expose the string as a typedef, to avoid bothering library users with custom comparison policies. Most of the interoperability concerns could be addressed by relaxing the requirement that traits_type match extacly in basic_string member functions which take basic_strings as arguments -- at least for those which don't involve comparison.
Nice theory, but nobody has ever tried it in practice. Not that there's any need to. std::string works, and nobody uses the 'Traits'. Besides, you'll still introduce unneeded string copies.

"Peter Dimov" <pdimov@mmltd.net> wrote in message news:00c501c414c8$4d7aba80$1d00a8c0@pdimov2...
Jonathan Turkanis wrote:
"Peter Dimov" <pdimov@mmltd.net> wrote in message news:004101c41369$2ca8cb90$1d00a8c0@pdimov2...
And for the string case, the downside to encoding a comparison in the type is that you'll now spend a lot of time converting strings (because most libraries - correctly - accept an ordinary std::string, regardless of what comparisons they might make underneath, or they'd expose implementation details in the interface.)
You can expose the string as a typedef, to avoid bothering library users with custom comparison policies. Most of the interoperability concerns could be addressed by relaxing the requirement that traits_type match extacly in basic_string member functions which take basic_strings as arguments -- at least for those which don't involve comparison.
Nice theory, but nobody has ever tried it in practice.
Sure -- it's not practical with the current basic_string.
Not that there's any need to. std::string works, and nobody uses the 'Traits'. Besides, you'll still introduce unneeded string copies.
These copies would mostly happen when a string is passed from one library or API to another; copying would occur there anyway, except with reference-counted implementations. Anyway, I'm not really advocating this style of programming. I just don't see why it should be made impossible by not providing a traits parameter (with all the junk removed, of course) .With basic_string, it's easy to ignore the traits parameter if you don't want to use it, as you've said. Jonathan

This is probably the best characterization of the traits/policy distinction I've heard. I don't agree entirely about basic_string, however; I think that the comparison functions such as char_traits::compare have to be made available through template parameters, otherwise you wouldn't be able to reuse basic_string if you want strings with different comparison criteria.
This is a problem with char_traits design - it mixes things that belong to traits and to policies.
Most of the stuff in char_traits, such as the typedefs, copy, move, to_int_type, eof could go in a genuine traits template, so that basic_string would look like this:
template<typename Ch, typename Comp = std::char_compare<Ch> > class basic_string;
We could do something like this. But as you have says yourself (and Herb Sutter in the book ) in majority of the cases it does not worse the trouble. In practice you couldn't change string class globally in whole application to use different comparison. In consequence you will pay with a lot of conversions. Though even what you wrote above is better than what we have now.
This wouldn't make a practical difference for strings, but it might mean that iostreams wouldn't need traits parameters at all -- I haven't verified this -- which would be a huge advantage.
And for many other classes that are trying to support Unicode.
Jonathan
Gennadiy.

We could do something like this. But as you have says yourself (and Herb Sutter in the book ) in majority of the cases it does not worse the
"Gennadiy Rozental" <gennadiy.rozental@thomson.com> wrote in message news:c429pi$h45$1@sea.gmane.org... trouble.
In practice you couldn't change string class globally in whole application to use different comparison. In consequence you will pay with a lot of conversions.
I basically agree, but as I said in a reply to Peter, the required conversions would be minimal in most cases if string functions such as constuctors and assignment operators were liberalized to accept specializations of basic_string with different traits types. Jonathan

Rozental, Gennadiy wrote:
In most part proposed design looks reasonable. I have only one major IMO concern.
Issue: (Major) Why traits are template parameter of converter? I've expressed my opinion in the matter before: Traits - as name suggest could not be policy. IOW should not be template parameters. Traits are type specific and an ability to supply them independently to the primary type in most cases leads to invalid/too complicated design. Traits are not only template parameters of public converter class but many other classes. IMO all of them should use S and T as template parameters instead.
I have to disagree. Traits are used as policies in too many designs, including the STL itself, and I don't see a problem with that. I agree
I don't say I like it either. Major issue with basic_string design IMO is that char_traits is template parameter
that traits classes are type specific, but they are used as policies precisely because of that: if the user of a parametrized facility wants a different treatment for a given type, she can't change *the* traits for the type, all she can do is pass in a different traits as a policy.
Here is how I see it. Trait is something type specific, IOW specific to type, IOW uniquely defined by type. If you could provide trait along with the type as a template parameter, that mean you could change it independently from the type, IOW you could define different value for trait still using the same type. For example if you have component C defined like:
template<typename T, typename Trait> struct C { ... };
You could instantiate it like C<MyT,TraitValue1> or C<MyT,TraitValue2>. So as you could see trait value is not uniquely defined by the type.
Proper design would be to have trait stand alone class, like this:
template<typename T> struct Trait { value = ... };
template<typename T> struct C { here we are using Trait<T>::value, where we used to use Trait. };
Now if the user needs to define trait value (or change from using default value provided by most traits designs), she just need to define explicit/partial specialization for this type or types family.
What if there is already an specialization? That's the typical case with standalone traits.
On the other hand policy is something that is orthogonal to the primary type (actually in policy based design there may not be any primary type, but just an orthogonal policies), IOW you could use different policies in conjunction with the same type. And natural place for the policy is along with type in component definition among the template parameters.
Policies must be orthogonal between themselves, but not neccesarily w.r.t the primary type(s). In fact, many common policies (from common policy-based designs) are not.
If this were not a policy, users would be stuck with the definition of the default traits class. I agree that this opens a window to all sort of problems in case a user plugs in an invalid traits, but I think that should not constitute a reason for fixing the traits into the converter. As always, "trust the programmer"
So again Trait is not a Policy and let's not mix them
I disagree. A trait can _function_ as a policy IMO. Well, I do follow your arguments but I'm still unconvinced. A traits is type-specific, yes, but not necessarily _unique_. You see it as unique, but why would it has to be like that? It seems that that fundamental point of your argument is that traits are uniquely defined by a type, and not just a type decoration. If this were true, then I would agree, but I don't see why a type can't have a set of "compatible" traits. It would benefit your argument if you had some backup. That is, some reference of others who think the same.
4. converter<>::convert converts only rvalue. Why? IMO we need second operation that works with lvalues. What if I want to convert int& into char&? This requires the target lvalue as a parameter instead of a return value. It could be done yes, but I don't see the reason. Why would want to do that?
For example for [de]serialization solutions. What is in your opinion is problem domain for numeric conversion?
Well, numeric conversions :-) Whenever you need to convert between numeric types... there is no particular problem domain for this general need. In a [de]serialization framework I would expect types to be serialized/deserialized the same, so I don't quite see the use case for a numeric conversion here. Fernando Cacciola SciSoft

Recent messages in the thread, "Numeric conversions lib comments," involve questions regarding what is a trait and what is a policy. I have my own ideas colored by MCD and other sources, but try as I might, I couldn't find any authoritative or explicit defintion of the terms. Considering how much they are bandied about here on Boost, perhaps it would be good to agree upon Boost definitions of the terms. That way, there is less room for confusion when those terms are used. To get the ball rolling, here are my definitions. They provide clear, non-overlapping concepts, which I think are important characteristics. Trait - A class template parameterized on a single type that associates information with that type. A traits class, therefore, provides an external, named grouping of metainformation, behavior, or both for that type. A trait class is never passed as a template parameter; it's name is ubiquitous. A traits class never has state. Policy - A class template passed to other templates for the purpose of providing a named grouping of metainformation, behavior, or both to those templates. Because it is a template parameter, different policy classes can be used as desired. In many cases, a policy class is used as a base class. What do you think? I know that my definitions mean that std::char_traits is a policy class, despite its name, and they probably deviate from some other ad hoc definitions. The question is whether these provide sound, distinct, and defensible concepts that could be codified for future use at Boost (and elsewhere). -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart <stewart@sig.com> writes:
Recent messages in the thread, "Numeric conversions lib comments," involve questions regarding what is a trait and what is a policy. I have my own ideas colored by MCD and other sources, but try as I might, I couldn't find any authoritative or explicit defintion of the terms. Considering how much they are bandied about here on Boost, perhaps it would be good to agree upon Boost definitions of the terms. That way, there is less room for confusion when those terms are used.
My view on "traits" is here: http://tinyurl.com/25db2
To get the ball rolling, here are my definitions. They provide clear, non-overlapping concepts, which I think are important characteristics.
Trait - A class template parameterized on a single type that associates information with that type. A traits class, therefore, provides an external, named grouping of metainformation, behavior, or both for that type. A trait class is never passed as a template parameter; it's name is ubiquitous.
Whoops, can't agree there. The boost type traits are passed as template parameters all the time: mpl::apply_if< is_pointer<X>, remove_pointer<X>, add_reference<X> >
A traits class never has state.
Policy - A class template passed to other templates for the purpose of providing a named grouping of metainformation,
I think a Policy might be a non-templated class.
behavior, or both to those templates. Because it is a template parameter, different policy classes can be used as desired. In many cases, a policy class is used as a base class.
What do you think? I know that my definitions mean that std::char_traits is a policy class, despite its name, and they probably deviate from some other ad hoc definitions. The question is whether these provide sound, distinct, and defensible concepts that could be codified for future use at Boost (and elsewhere).
I think your definitions are mostly on target, but I think where you go wrong is that traits/policies has less to do with how a template is defined than how it's used. -- Dave Abrahams Boost Consulting www.boost-consulting.com

From: David Abrahams <dave@boost-consulting.com>
Rob Stewart <stewart@sig.com> writes:
To get the ball rolling, here are my definitions. They provide clear, non-overlapping concepts, which I think are important characteristics.
Before launching into a formal definition, I should have tried to characterize my ideas better.
Trait - A class template parameterized on a single type that associates information with that type. A traits class, therefore, provides an external, named grouping of metainformation, behavior, or both for that type. A trait class is never passed as a template parameter; it's name is ubiquitous.
Whoops, can't agree there. The boost type traits are passed as template parameters all the time:
mpl::apply_if< is_pointer<X>, remove_pointer<X>, add_reference<X> >
That's not quite what I meant. To me, a traits class is the one and only supplier of that information for a given type (within a library or namespace anyway). You can make it a class template -- and would almost never choose to not do that -- and specialize it for various types, but the traits class/specializations are the sole source of that information. A traits class can provide types (typedefs and nested types), static constant values, and static mfs. IOW, if you want "character traits" as defined by the Standard Library, you use std::char_traits<T>. If you want character traits as defined by another library (or namespace), you use some other class. However, within a library, there would never be more than one class from which to choose to get character traits. mpl::apply_if wants a Boolean condition and two type choices from which to select. apply_if doesn't use any of those template parameters as a trait. It isn't doing what I was trying to describe in my definition, so my definition is faulty in this regard.
A traits class never has state.
By that I meant no non-static state. For that matter, it has no non-static members at all. I should have put *that* in my definition.
Policy - A class template passed to other templates for the purpose of providing a named grouping of metainformation,
I think a Policy might be a non-templated class.
Oops! You're right.
behavior, or both to those templates. Because it is a template parameter, different policy classes can be used as desired. In many cases, a policy class is used as a base class.
What do you think? I know that my definitions mean that std::char_traits is a policy class, despite its name, and they probably deviate from some other ad hoc definitions. The question is whether these provide sound, distinct, and defensible concepts that could be codified for future use at Boost (and elsewhere).
I think your definitions are mostly on target, but I think where you go wrong is that traits/policies has less to do with how a template is defined than how it's used.
I think that std::char_traits is actually a traits class because it is the sole provider of that information in the Standard Library and its present use within the library isn't the only way it can be used. I was thinking only about its use as a template parameter within the Standard Library. In that case, as you and others have pointed out quite rightly, it is being *used* as a policy and so it is the template parameter name that is wrong. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Well I think in terms of code, and it really is quite simple IMHO: Traits look like this: template< typename T > class SomeTraits { // Stuff that tells us about T }; and Policies look like this template< typename Policy > class SomeThing { // Delegates some behaviour to Policy }; IOW, traits are class templates and policies are template parameters so there really can't be any confusion between the two. So in the case std::basic_string template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > class basic_string { "char_traits" is a traits class template but "traits" is actually a policy template parameter. It is quite reasonable for specialisations of traits templates to be used as arguments to policy parameters, which is exactly what happens when we write std::basic_string< char,std::char_traits<char> > But I don't think there is anything in basic_string that requires the template argument to be a specialisation of a class template. I think it would be quite legitimate to write class MyFunkyCharBehaviour { /*...*/ }; typedef std::basic_string<char,MyFunkyCharBehaviour> MyFunkyString; so the "traits" parameter is indeed misnamed. However std::char_traits is most definitely a traits template and doesn't *have* to be used as a policy. In fact std::basic_string could have been written to exclusively use char_traits *instead* of a policy. Mark

"Mark Rodgers" <mark.rodgers@cadenza.co.nz> wrote in message news:002601c41836$33148560$0100a8c0@cadenza.co.nz...
Well I think in terms of code, and it really is quite simple IMHO:
Traits look like this:
template< typename T > class SomeTraits { // Stuff that tells us about T };
and Policies look like this
template< typename Policy > class SomeThing { // Delegates some behaviour to Policy };
IOW, traits are class templates and policies are template parameters so there really can't be any confusion between the two. So in the case std::basic_string
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > class basic_string {
"char_traits" is a traits class template but "traits" is actually a policy template parameter.
That's is namely the problem I have with basic_string design. Trais class is used as policy. Actually it's even worse - char_traits contain partially functionality that may belong to some kind of policy (for example comparison method). IMO it should be separated.
It is quite reasonable for specialisations of traits templates to be used as arguments to policy parameters, which is exactly what happens when we write
std::basic_string< char,std::char_traits<char> >
But I don't think there is anything in basic_string that requires the template argument to be a specialisation of a class template. I think it would be quite legitimate to write
class MyFunkyCharBehaviour { /*...*/ }; typedef std::basic_string<char,MyFunkyCharBehaviour> MyFunkyString;
Exactly, so we could use complete different class that will define different trait values. And this is not good IMO.
so the "traits" parameter is indeed misnamed.
However std::char_traits is most definitely a traits template and doesn't *have* to be used as a policy. In fact std::basic_string could have been written to exclusively use char_traits *instead* of a policy.
IMO it should've been.
Mark
Gennadiy.

From: "Gennadiy Rozental" <gennadiy.rozental@thomson.com>
"Mark Rodgers" <mark.rodgers@cadenza.co.nz> wrote in message news:002601c41836$33148560$0100a8c0@cadenza.co.nz...
IOW, traits are class templates and policies are template parameters so there really can't be any confusion between the two. So in the case std::basic_string
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > class basic_string {
"char_traits" is a traits class template but "traits" is actually a policy template parameter.
That's is namely the problem I have with basic_string design. Trais class is used as policy. Actually it's even worse - char_traits contain partially functionality that may belong to some kind of policy (for example comparison method). IMO it should be separated.
std::char_traits is a traits class. It also happens that std::basic_string accepts a policy for controlling how it does various things. For expediency, std::char_traits provides the interface expected of std::basic_string's policy class. Thus, std::char_traits is used as the default policy class for std::basic_string. That doesn't stop std::char_traits from being a traits class. You can still write code that references -- without making it a template parameter -- std::char_traits<T>::foo.
It is quite reasonable for specialisations of traits templates to be used as arguments to policy parameters, which is exactly what happens when we write
std::basic_string< char,std::char_traits<char> >
But I don't think there is anything in basic_string that requires the template argument to be a specialisation of a class template. I think it would be quite legitimate to write
class MyFunkyCharBehaviour { /*...*/ }; typedef std::basic_string<char,MyFunkyCharBehaviour> MyFunkyString;
Exactly, so we could use complete different class that will define different trait values. And this is not good IMO.
There's nothing wrong with that. It is std::basic_string's interface that provides for the use of a policy class. That std::char_traits happens to be the most appropriate -- it rarely isn't -- implementation of that policy is beside the point. You can argue that std::basic_string shouldn't have such a policy parameter, and you'd probably be right, but that's not std::char_traits' fault. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

There's nothing wrong with that. It is std::basic_string's interface that provides for the use of a policy class. That std::char_traits happens to be the most appropriate -- it rarely isn't -- implementation of that policy is beside the point. You can argue that std::basic_string shouldn't have such a policy parameter, and you'd probably be right, but that's not std::char_traits' fault.
That's right. It's basic_string fault, which should've used char_traits by name in basic_string implementation. The only note to the char_traits design may be that compare method does not nessesary belong to it. Gennadiy.

Gennadiy Rozental wrote:
There's nothing wrong with that. It is std::basic_string's interface that provides for the use of a policy class. That std::char_traits happens to be the most appropriate -- it rarely isn't -- implementation of that policy is beside the point. You can argue that std::basic_string shouldn't have such a policy parameter, and you'd probably be right, but that's not std::char_traits' fault.
That's right. It's basic_string fault, which should've used char_traits by name in basic_string implementation.
I don't want to turn this into a std::string discussion, but if basic_string used char_traits by name, how would you define two different string types using char*, one with case-sensitive comparison and one without? With basic_string the way it is, it's possible; the way you're proposing, I don't see how to do it. There are lots of problems with basic_string, but template<typename T, typename traits = xxx<T> > class foo; isn't one of them. Bob

That's right. It's basic_string fault, which should've used char_traits by name in basic_string implementation.
I don't want to turn this into a std::string discussion, but if basic_string used char_traits by name, how would you define two different string types using char*, one with case-sensitive comparison and one without? With basic_string the way it is, it's possible; the way you're proposing, I don't see how to do it.
Look under "Numeric convertion lib comments" thread for more details, but short answer: don't. If you need case insensitive comparison use external predicate. No reason to change string type for that. Gennadiy.

Gennadiy Rozental wrote:
That's right. It's basic_string fault, which should've used char_traits
by
name in basic_string implementation.
I don't want to turn this into a std::string discussion, but if basic_string used char_traits by name, how would you define two different string types using char*, one with case-sensitive comparison and one without? With basic_string the way it is, it's possible; the way you're proposing, I don't see how to do it.
Look under "Numeric convertion lib comments" thread for more details, but short answer: don't. If you need case insensitive comparison use external predicate. No reason to change string type for that.
I read the thread. Here's what you wrote on 3/23/2004:
Here is how I see it. Trait is something type specific, IOW specific to type, IOW uniquely defined by type. If you could provide trait along with the type as a template parameter, that mean you could change it independently from the type, IOW you could define different value for trait still using the same type. For example if you have component C defined like:
template<typename T, typename Trait> struct C { ... };
You could instantiate it like C<MyT,TraitValue1> or C<MyT,TraitValue2>. So as you could see trait value is not uniquely defined by the type.
So what? The only thing I'm getting from this as to why traits should be "uniquely defined by the type" is because you've defined traits that way. But I don't see why traits have to be defined that way. I don't see what bad thing happens if C is defined as above.
Proper design would be to have trait stand alone class, like this:
template<typename T> struct Trait { value = ... };
template<typename T> struct C { here we are using Trait<T>::value, where we used to use Trait. };
Now if the user needs to define trait value (or change from using default value provided by most traits designs), she just need to define explicit/partial specialization for this type or types family.
Unless, as someone else pointed out, there already exists such a specialization.
On the other hand policy is something that is orthogonal to the primary type (actually in policy based design there may not be any primary type, but just an orthogonal policies), IOW you could use different policies in conjunction with the same type. And natural place for the policy is along with type in component definition among the template parameters.
You seem to be arguing that template<typename T, typename U = traits<T> > class Foo { }; is wrong because it blurs the distinction between traits and policies. I say "so what?" If the problem is best solved by blurring these ideas, blur away. No one seems to have yet been able to define "traits" and "policies" very well anyway, so what are we blurring? On 1/3/2004, you wrote
I've expressed my opinion in the matter before: Traits - as name suggest could not be policy. IOW should not be template parameters. Traits are type specific and an ability to supply them independently to the primary type in most cases leads to invalid/too complicated design.
The way I read this, your use of "most cases" means you agree there are some cases where the above use of traits passed into a template is justified and acceptable. This seems to contradict the idea above that traits can never be used this way. Can you clarify please? Bob

From: Robert Bell <belvis@imageworks.com>
Gennadiy Rozental wrote:
Here is how I see it. Trait is something type specific, IOW specific to type, IOW uniquely defined by type. If you could provide trait along with the type as a template parameter, that mean you could change it independently from the type, IOW you could define different value for trait still using the same type. For example if you have component C defined like:
template<typename T, typename Trait> struct C { ... };
You could instantiate it like C<MyT,TraitValue1> or C<MyT,TraitValue2>. So as you could see trait value is not uniquely defined by the type.
So what? The only thing I'm getting from this as to why traits should be "uniquely defined by the type" is because you've defined traits that way. But I don't see why traits have to be defined that way. I don't see what bad thing happens if C is defined as above.
If trait is synonymous with policy, then why have both? When policies hit the scene, they were like "traits on steroids," as Andrei put it. They pushed the envelope in terms of what a traits class could be used to do. The result, however, didn't look like the traits class stuff that had been used prior to that point, save for std::char_traits in the likes of std::basic_string. As a result, I think we wound up with something new, not just a slight variation on the status quo. Thus, a traits class is one that can be specialized for various types, but is always known by one name in all uses. By contrast, a policy class is one passed as a template argument for use specifically to alter behavior according to predefined points of customization.
Proper design would be to have trait stand alone class, like this:
template<typename T> struct Trait { value = ... };
template<typename T> struct C { here we are using Trait<T>::value, where we used to use Trait. };
Now if the user needs to define trait value (or change from using default value provided by most traits designs), she just need to define explicit/partial specialization for this type or types family.
Unless, as someone else pointed out, there already exists such a specialization.
On the other hand policy is something that is orthogonal to the primary type (actually in policy based design there may not be any primary type, but just an orthogonal policies), IOW you could use different policies in conjunction with the same type. And natural place for the policy is along with type in component definition among the template parameters.
You seem to be arguing that
template<typename T, typename U = traits<T> > class Foo { };
is wrong because it blurs the distinction between traits and policies. I
I think Gennadiy would agree that this is fine because U is a policy template parameter defined to use at least a subset of traits' interface. If U isn't well-defined and traits becomes the definition of U, even though Foo doesn't use all of traits' interface, then the design of Foo is poor. That would seem to be the case with std::basic_string and std::char_traits. I haven't looked at the implementation with this in mind, but I'm guessing that std::basic_string doesn't use all of std::char_traits interface, and yet the "traits" parameter of std::basic_string isn't defined separately.
say "so what?" If the problem is best solved by blurring these ideas, blur away. No one seems to have yet been able to define "traits" and "policies" very well anyway, so what are we blurring?
*If* there is value, as I of course think there is, in maintaining a distinction for accuracy in discourse, then we're needlessly combining separate notions. If few think the distinction is important, then we should simply choose one or the other term to avoid confusion.
On 1/3/2004, you wrote
I've expressed my opinion in the matter before: Traits - as name suggest could not be policy. IOW should not be template parameters. Traits are type specific and an ability to supply them independently to the primary type in most cases leads to invalid/too complicated design.
The way I read this, your use of "most cases" means you agree there are some cases where the above use of traits passed into a template is justified and acceptable. This seems to contradict the idea above that traits can never be used this way. Can you clarify please?
If an existing traits class provides (at least) the interface needed for a template's policy class, then using the traits class as that policy should be fine. The fact that the template parameter is a policy means that the template is allowing for other implementations of that interface. That doesn't make the traits class any less the one definition of those traits. Put another way, any other classes implemented to be used as the template's policy argument won't be used as traits; they'll only be used as the template's arguments. The distinction provides some clarity when using the phrases "traits class" or "policy class." When someone says "policy class," you immediately know that they mean something passed as a template argument or the template parameter used within the template to effect behavioral changes. When someone says "traits class," you immediately know that they mean something customizable for each distinct type, but not for each template wishing to use it. Those are quite different things and disambiguiating them via different names is sensible. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Rob Stewart" <stewart@sig.com> wrote in message news:200404051344.i35Diq626463@entwistle.systems.susq.com... [analysis snipped] Yes to the above analysis :-)
The distinction provides some clarity when using the phrases "traits class" or "policy class." When someone says "policy class," you immediately know that they mean something passed as a template argument or the template parameter used within the template to effect behavioral changes. When someone says "traits class," you immediately know that they mean something customizable for each distinct type, but not for each template wishing to use it. Those are quite different things and disambiguiating them via different names is sensible.
And yes :-) BTW the thread has clarified a lot regarding policies and traits for me.... well worthwhile regards Andy Little

On the other hand policy is something that is orthogonal to the primary type (actually in policy based design there may not be any primary type, but just an orthogonal policies), IOW you could use different policies in conjunction with the same type. And natural place for the policy is along with type in component definition among the template parameters.
You seem to be arguing that
template<typename T, typename U = traits<T> > class Foo { };
is wrong because it blurs the distinction between traits and policies. I
I think Gennadiy would agree that this is fine because U is a policy template parameter defined to use at least a subset of traits' interface.
I agree. It may even theoretically be possible that Foo uses U interface that has nothing to do with trait<T> being the trait. But! It would make me very wary. Even though I admit above is possible, in most cases it's sign of incorrect design.
If U isn't well-defined and traits becomes the definition of U, even though Foo doesn't use all of traits' interface, then the design of Foo is poor. That would seem to be the case with std::basic_string and std::char_traits. I haven't looked at the implementation with this in mind, but I'm guessing that std::basic_string doesn't use all of std::char_traits interface, and yet the "traits" parameter of std::basic_string isn't defined separately.
I am not sure where you going with "doesn't use all of std::char_traits" IMO it does not matter which part if char_traits interface basic_string is using.. In any case it should've referred to it by name and not through template parameter.
say "so what?" If the problem is best solved by blurring these ideas, blur away. No one seems to have yet been able to define "traits" and "policies" very well anyway, so what are we blurring?
*If* there is value, as I of course think there is, in maintaining a distinction for accuracy in discourse, then we're needlessly combining separate notions. If few think the distinction is important, then we should simply choose one or the other term to avoid confusion.
On 1/3/2004, you wrote
I've expressed my opinion in the matter before: Traits - as name suggest could not be policy. IOW should not be template parameters. Traits are type specific and an ability to supply them independently to the primary type in most cases leads to invalid/too complicated design.
The way I read this, your use of "most cases" means you agree there are some cases where the above use of traits passed into a template is justified and acceptable. This seems to contradict the idea above that traits can never be used this way. Can you clarify please?
If an existing traits class provides (at least) the interface needed for a template's policy class, then using the traits class as that policy should be fine. The fact that the template parameter is a policy means that the template is allowing for other implementations of that interface. That doesn't make the traits class any less the one definition of those traits. Put another way, any other classes implemented to be used as the template's policy argument won't be used as traits; they'll only be used as the template's arguments.
The distinction provides some clarity when using the phrases "traits class" or "policy class." When someone says "policy class," you immediately know that they mean something passed as a template argument or the template parameter used within the template to effect behavioral changes. When someone says "traits class," you immediately know that they mean something customizable for each distinct type, but not for each template wishing to use it. Those are quite different things and disambiguiating them via different names is sensible.
Very true. Gennadiy.

From: "Gennadiy Rozental" <gennadiy.rozental@thomson.com>
You seem to be arguing that
template<typename T, typename U = traits<T> > class Foo { };
is wrong because it blurs the distinction between traits and policies. I
I think Gennadiy would agree that this is fine because U is a policy template parameter defined to use at least a subset of traits' interface.
I agree. It may even theoretically be possible that Foo uses U interface that has nothing to do with trait<T> being the trait. But! It would make me very wary. Even though I admit above is possible, in most cases it's sign of incorrect design.
I'm not sure it warrants wariness. If Foo defines semantics for its U policy and those semantics just happen to be fulfilled by a traits class, what's the problem with using the traits class as the policy argument? It doesn't mean other policy classes aren't possible, just that there is a convenient one available in an existing traits class.
If U isn't well-defined and traits becomes the definition of U, even though Foo doesn't use all of traits' interface, then the design of Foo is poor. That would seem to be the case with std::basic_string and std::char_traits. I haven't looked at the implementation with this in mind, but I'm guessing that std::basic_string doesn't use all of std::char_traits interface, and yet the "traits" parameter of std::basic_string isn't defined separately.
I am not sure where you going with "doesn't use all of std::char_traits" IMO it does not matter which part if char_traits interface basic_string is using.. In any case it should've referred to it by name and not through template parameter.
I mean that std::basic_string's "traits" policy parameter may only require a subset of what is defined in std::char_traits. If that's the case, it is a mistake, in my mind, not to separately document the required semantics for that policy. Thus, while std::char_traits may fulfill the requirements of that policy, it is a superset that should be documented separately. Whether std::basic_string should have a policy or should just use a traits class is another matter entirely. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

From: "Mark Rodgers" <mark.rodgers@cadenza.co.nz>
Well I think in terms of code, and it really is quite simple IMHO:
Traits look like this:
template< typename T > class SomeTraits { // Stuff that tells us about T };
and Policies look like this
template< typename Policy > class SomeThing { // Delegates some behaviour to Policy };
IOW, traits are class templates and policies are template parameters so there really can't be any confusion between the two. So in the case
I think that misses an important traits trait 8^) that I didn't communicate well: for a given namespace/library, there is only one traits class for a given set of attributes. You can create other traits that collect different information, collect the same information with a different interface, but for a given interface and set of information, there's only one traits class.
std::basic_string
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > class basic_string {
"char_traits" is a traits class template but "traits" is actually a policy template parameter. It is quite reasonable for specialisations of traits templates to be used as arguments to policy parameters, which is exactly
That's reasonable only if the traits class provides the semantics expected of the policy which is, obviously, the case in your basic_string example.
what happens when we write
std::basic_string< char,std::char_traits<char> >
I agree.
But I don't think there is anything in basic_string that requires the template argument to be a specialisation of a class template. I think it would be quite legitimate to write
class MyFunkyCharBehaviour { /*...*/ }; typedef std::basic_string<char,MyFunkyCharBehaviour> MyFunkyString;
so the "traits" parameter is indeed misnamed.
Right.
However std::char_traits is most definitely a traits template and doesn't *have* to be used as a policy. In fact std::basic_string could have been written to exclusively use char_traits *instead* of a policy.
Right. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Rob Stewart" <stewart@sig.com> wrote in message news:200404012013.i31KDOP25003@entwistle.systems.susq.com...
Recent messages in the thread, "Numeric conversions lib comments," involve questions regarding what is a trait and what is a policy.
A trait is a part of the definition of an entity. A policy is applied to an entity to modify a trait or traits of the entity. Shorter Oxford English Dictionary (abbreviated) " Policy 1 A constitution,polity. (Now rare or obsolete) 2. Government, administration; political science. -1796 3. Political sagacity; statecraft ; diplomacy; in bad sense, political cunning.(Late middle english) 4. In reference to conduct or act generally: prudent, expedient , or advantageous course of action; as a quality of the agent: sagacity, shrewdness, artfulness; in bad sense, cunning, craftiness.(Late middle english). A device , expedient contrivance; a crafty device, stratagem, trick -1849. 5. A course of action adopted and pursued by a government, party, ruler or statesman, etc; any course of action adopted as advantageous or expedient. (The chief living sense). (Late midle english). Trait 1. Shot of any kind. 2. A stroke made with pen or pencil; a short line; a touch(in a picture) 1589. 3. a line or lineament of the face; a feature 1773. ("Here face is somewhat altered. The traits have become more delicate" Shelley) 4. A distinguishing quality; a characteristic 1752. 4b A 'touch' of some quality (Now rare 1815) 5 A stroke or flash of wit, sarcasm or pleasantry -1859 " regards Andy Little

A trait is a part of the definition of an entity.
That's right.
A policy is applied to an entity to modify a trait or traits of the entity.
I think in this case mixure of terms is only misleading. What trait does checking policy modify CheckingPolicy in SmartPointer? I would just say: "A policy is applied to an entity to modify it". It could modify it's defintion, behavior, both, e.t.c.
Shorter Oxford English Dictionary (abbreviated) " Policy
5. A course of action adopted and pursued by a government, party, ruler or statesman, etc; any course of action adopted as advantageous or expedient. (The chief living sense). (Late midle english).
This looks like most close.
Trait
4. A distinguishing quality; a characteristic 1752.
This looks like most close.
regards
Andy Little
Gennadiy

"Gennadiy Rozental" <gennadiy.rozental@thomson.com> writes:
A trait is a part of the definition of an entity.
That's right.
Absolutely not. A key trait of traits is that they're non-intrusive. They create an association with that can be defined *after* the type argument is defined. See http://www.boost.org/more/generic_programming.html#traits -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uptaqlaqz.fsf@boost-consulting.com...
"Gennadiy Rozental" <gennadiy.rozental@thomson.com> writes:
A trait is a part of the definition of an entity.
That's right.
Absolutely not. A key trait of traits is that they're non-intrusive. They create an association with that can be defined *after* the type argument is defined. See http://www.boost.org/more/generic_programming.html#traits
I do undersand that. But I still believe that trait specification is part of definition. That is why I think that the best place for it is right after "real" type definition. For example, for Solaris 4.2 compiler I am frequently using construct like: struct myType{}; template<> is_pointer<myType*> { enum {value = true; } }; temaplte<> iterator_traits<myType*> { ... }; Gennadiy.

"Gennadiy Rozental" <gennadiy.rozental@thomson.com> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uptaqlaqz.fsf@boost-consulting.com...
"Gennadiy Rozental" <gennadiy.rozental@thomson.com> writes:
A trait is a part of the definition of an entity.
That's right.
Absolutely not. A key trait of traits is that they're non-intrusive. They create an association with that can be defined *after* the type argument is defined. See http://www.boost.org/more/generic_programming.html#traits
I do undersand that. But I still believe that trait specification is part of definition.
Not if you want to describe the properties of some 3rd-party class: #include <3rd_party/smart_ptr.hpp> template <class T> struct is_dereferenceable<third_party::smart_ptr<T> > : mpl::true {}; -- Dave Abrahams Boost Consulting www.boost-consulting.com

I do undersand that. But I still believe that trait specification is part of definition.
Not if you want to describe the properties of some 3rd-party class:
#include <3rd_party/smart_ptr.hpp>
template <class T> struct is_dereferenceable<third_party::smart_ptr<T> > : mpl::true {};
I imagine you wouldn't do it 10 times in your code and most definetlety you wouln't define it differently in different headers. Most probable you introduce 3rd_party_smart_ptr_wrap.hpp that contains above trait specification and use everywhere instead of 3rd_party/smart_ptr.hpp. So in this case from my POV you *updated* smart_ptr definition and use this updated definition instead of original one. Gennadiy.

"Gennadiy Rozental" <gennadiy.rozental@thomson.com> writes:
I do undersand that. But I still believe that trait specification is part of definition.
Not if you want to describe the properties of some 3rd-party class:
#include <3rd_party/smart_ptr.hpp>
template <class T> struct is_dereferenceable<third_party::smart_ptr<T> > : mpl::true {};
I imagine you wouldn't do it 10 times in your code and most definetlety you wouln't define it differently in different headers. Most probable you introduce 3rd_party_smart_ptr_wrap.hpp that contains above trait specification and use everywhere instead of 3rd_party/smart_ptr.hpp. So in this case from my POV you *updated* smart_ptr definition and use this updated definition instead of original one.
So if I write a free function that accepts third_party::smart_ptr<T> arguments I'm also updating the smart_ptr definition? You must have a funny definition of "definition". -- Dave Abrahams Boost Consulting www.boost-consulting.com

I do understand that. But I still believe that trait specification is part of definition.
Not if you want to describe the properties of some 3rd-party class:
#include <3rd_party/smart_ptr.hpp>
template <class T> struct is_dereferenceable<third_party::smart_ptr<T> > : mpl::true {};
I imagine you wouldn't do it 10 times in your code and most definetlety you wouldn't define it differently in different headers. Most probable you introduce 3rd_party_smart_ptr_wrap.hpp that contains above trait specification and use everywhere instead of 3rd_party/smart_ptr.hpp. So in this case from my POV you *updated* smart_ptr definition and use this updated definition instead of original one.
So if I write a free function that accepts third_party::smart_ptr<T> arguments I'm also updating the smart_ptr definition?
In some rare cases - yes.
You must have a funny definition of "definition".
Ok. I admit using word definition is at best stretch. But let me give this imaginary example where I will try to explain what I mean. Let say for the Project1 we defined a house model like this: House is a big cube. Now for the Project1 it was enough and we got away with this "incomplete" definition. For the Project2 we start working with objects has or has not windows and doors. So we added following "updates to definition" House has windows. House has doors. So what is above statements in regards to our House model. It's not a [part of] definition, because definition was done earlier. But it does not mean that houses we model in Project1 did not have windows or doors. So above two statements are not part of definition, but part of what House is actually is. You may argue that by making additional specification we are essentially defining new model: House with doors and windows. But I do not see why should we? smart_ptr is still smart_ptr even though you added statement that it is dereferenceable. It was dereferenceble by definition, you just did not have means to ask it before. Ok, above is most probably is just a gibberish. After all it's not that important how you look at this. You may as well consider traits as representative of the orthogonal to models definitions universe of concepts and categories. Or may be it just somewhere in intersection. Gennadiy.

Gennadyi wrote: [snip]
You must have a funny definition of "definition".
Ok. I admit using word definition is at best stretch. But let me give this imaginary example where I will try to explain what I mean.
Let say for the Project1 we defined a house model like this:
House is a big cube.
Now for the Project1 it was enough and we got away with this "incomplete" definition. For the Project2 we start working with objects has or has not windows and doors. So we added following "updates to definition"
House has windows. House has doors.
So what is above statements in regards to our House model. It's not a [part of] definition, because definition was done earlier. But it does not mean that houses we model in Project1 did not have windows or doors. So above two statements are not part of definition, but part of what House is actually is.
You may argue that by making additional specification we are essentially defining new model: House with doors and windows. But I do not see why should we? smart_ptr is still smart_ptr even though you added statement that it is dereferenceable. It was dereferenceble by definition, you just did not have means to ask it before.
This extra-typical "adornments" are part of what I would call a Feature Model. So, those stated relations constitute part of the Concept's definition. This is what Andy mentioned as well, and I think a few of us see here, the traits being used to define the Concept.
Ok, above is most probably is just a gibberish. After all it's not that important how you look at this. You may as well consider traits as representative of the orthogonal to models definitions universe of concepts and categories. Or may be it just somewhere in intersection.
It is not gibberish. As you know, one has to be careful of using words in a non-C++ way. /David

"David Bergman" <davidb@home.se> writes:
You may argue that by making additional specification we are essentially defining new model: House with doors and windows. But I do not see why should we? smart_ptr is still smart_ptr even though you added statement that it is dereferenceable. It was dereferenceble by definition, you just did not have means to ask it before.
This extra-typical "adornments" are part of what I would call a Feature Model. So, those stated relations constitute part of the Concept's definition. This is what Andy mentioned as well, and I think a few of us see here, the traits being used to define the Concept.
Yes, associated types are an essential element of Concepts, and the associated types and a method to reach them (often traits) is part of the Concept definition. C++ types, however, are not Concepts, and trait specializations are not part of the definitions of those C++ types. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David A. wrote:
This extra-typical "adornments" are part of what I would call a Feature Model. So, those stated relations constitute part of the Concept's definition. This is what Andy mentioned as well, and I think a few of us see here, the traits being used to define the Concept.
Yes, associated types are an essential element of Concepts, and the associated types and a method to reach them (often traits) is part of the Concept definition. C++ types, however, are not Concepts, and trait specializations are not part of the definitions of those C++ types.
Totally correct. I will try to avoid using the word "definition" without being perfectly clear that I am talking about GP concepts, since Boost should definitely take the "C++" or "C++ type" to be implicit. You are right. /David

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uptaqlaqz.fsf@boost-consulting.com...
"Gennadiy Rozental" <gennadiy.rozental@thomson.com> writes:
A trait is a part of the definition of an entity.
That's right.
Absolutely not. A key trait of traits is that they're non-intrusive. They create an association with that can be defined *after* the type argument is defined.
Surely a trait is *part of the *definition* * of an *entity* in a wider sense. (perhaps *definition* has wrong connotations) A type declaration may be *one part * of a larger *entity* including it and (for example) its operations, traits are parts of the wider entity too. traits mechanism is one mechanism for associating parts of the wider entity. (Another is function params via ADL etc) But the root of the problem/thread is exactly what is a trait , or traits and what is a policy. ie to try to come up with an ambiguous specification of the word trait ,traits and policy in a C++ context. FWIW A trait for an entity is used to describe a feature of the entity, usually by parameterising the entity or some type involved in the entity via a traits mechanism. (The traits mechanism associates an entity (usually a type) with a particular family of traits ). A policy customises (part of) an entity, usually by providing an (alternative) implementation of (some) functionality of the entity. non UDT examples: sizeof // has characteristics of a trait. Useful but cant change it atexit // has characteristics of a policy. Usually has a default functionality but can customise it regards Andy Little

Andy Little wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uptaqlaqz.fsf@boost-consulting.com...
"Gennadiy Rozental" <gennadiy.rozental@thomson.com> writes:
A trait is a part of the definition of an entity.
That's right.
Absolutely not. A key trait of traits is that they're non-intrusive. They create an association with that can be defined *after* the type argument is defined.
Surely a trait is *part of the *definition* * of an *entity* in a wider sense. (perhaps *definition* has wrong connotations)
Perhaps. It seems that the crucial distinction is that an entity's definition is complete without the trait; traits are not part of the definition of an entity, they add on to what the program can know (or do) with the entity. Using phrases like "a trait is part of the definition of an entity" confuses the issue because of the use of the word "definition". class Foo { // Foo completely defined here }; template<typename T> struct traits { // typedefs, etc. }; traits<Foo> doesn't change the definition of Foo. It doesn't even extend the definition of Foo. void F(Foo& x) { // no mention of traits<Foo> anywhere } All of x's behavior in F() is completely determined by Foo's definition, and not affected by traits<Foo> at all.
A type declaration may be *one part * of a larger *entity* including it and (for example) its operations, traits are parts of the wider entity too. traits mechanism is one mechanism for associating parts of the wider entity. (Another is function params via ADL etc)
But the root of the problem/thread is exactly what is a trait , or traits and what is a policy. ie to try to come up with an ambiguous specification of the word trait ,traits and policy in a C++ context.
FWIW
A trait for an entity is used to describe a feature of the entity, usually by parameterising the entity or some type involved in the entity via a traits mechanism. (The traits mechanism associates an entity (usually a type) with a particular family of traits ).
A policy customises (part of) an entity, usually by providing an (alternative) implementation of (some) functionality of the entity.
For myself, I'm leaning towards the "xxx is a traits or a policy depending on how it's used" viewpoint. I find the template<typename T, typename traits_or_policy = traits<T> > class Foo { }; example pretty compelling. Whether or not this is an example of good design is a red herring; because this idiom can be misused does not affect the point that whether traits_or_policy is used as a traits or policy class depends on how it's used by the client of Foo. Bob

From: Robert Bell <belvis@imageworks.com>
Andy Little wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uptaqlaqz.fsf@boost-consulting.com...
Surely a trait is *part of the *definition* * of an *entity* in a wider sense. (perhaps *definition* has wrong connotations)
Perhaps. It seems that the crucial distinction is that an entity's definition is complete without the trait; traits are not part of the definition of an entity, they add on to what the program can know (or do) with the entity.
I was bothered by it, too, but I didn't reply before now. You're right. The traits augment a type with additional information needed in a context beyond the context in which it was created.
Using phrases like "a trait is part of the definition of an entity" confuses the issue because of the use of the word "definition".
Yeah. I agree.
For myself, I'm leaning towards the "xxx is a traits or a policy depending on how it's used" viewpoint. I find the
template<typename T, typename traits_or_policy = traits<T> > class Foo { };
example pretty compelling. Whether or not this is an example of good design is a red herring; because this idiom can be misused does not affect the point that whether traits_or_policy is used as a traits or policy class depends on how it's used by the client of Foo.
Whoa! I think you've taken the notion past what we've been discussing. "traits" in your example isn't a traits class or policy class depending upon how its used. If the name is to be believed, "traits" is a traits class because it associates stuff with T. However, within Foo, the template parameter traits_or_policy is a policy class. Let me illustrate: template<typename T, typename policy = traits<T> > class Foo { Foo() { policy::foo(traits<T>::bar); } }; traits<T> is both a traits and a policy class within Foo. The ctor unconditionally uses traits<T>::bar to get something associated with T. That isn't affected by the policy class given as the second template parameter. By contrast, the ctor uses the policy class when it calls policy::foo(). That the second template argument happens to be traits<T> is immaterial. It could be another class, thus affecting the ctor's behavior. (A traits class isn't restricted from having static member functions and a policy class isn't restricted from having static data members, I just haven't shown them in this example.) -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Robert Bell" <belvis@imageworks.com> wrote in message news:406DBA03.5@imageworks.com...
Andy Little wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uptaqlaqz.fsf@boost-consulting.com...
"Gennadiy Rozental" <gennadiy.rozental@thomson.com> writes:
A trait is a part of the definition of an entity.
That's right.
Absolutely not. A key trait of traits is that they're non-intrusive. They create an association with that can be defined *after* the type argument is defined.
Surely a trait is *part of the *definition* * of an *entity* in a wider sense. (perhaps *definition* has wrong connotations)
Perhaps. It seems that the crucial distinction is that an entity's definition is complete without the trait; traits are not part of the definition of an entity, they add on to what the program can know (or do) with the entity.
Using phrases like "a trait is part of the definition of an entity" confuses the issue because of the use of the word "definition".
Yep...sorry .
class Foo { // Foo completely defined here };
template<typename T> struct traits { // typedefs, etc. };
traits<Foo> doesn't change the definition of Foo. It doesn't even extend the definition of Foo.
void F(Foo& x) { // no mention of traits<Foo> anywhere }
All of x's behavior in F() is completely determined by Foo's definition, and not affected by traits<Foo> at all.
perhaps traits <Foo> is not necessary ;-)
For myself, I'm leaning towards the "xxx is a traits or a policy depending on how it's used" viewpoint. I find the
template<typename T, typename traits_or_policy = traits<T> > class Foo { };
example pretty compelling. Whether or not this is an example of good design is a red herring; because this idiom can be misused does not affect the point that whether traits_or_policy is used as a traits or policy class depends on how it's used by the client of Foo.
I thought I'd try an example to see what happens. whether this is best example I dont know....whatever Many more variants of course possible. operator()() could be moved into multiply_traits etc which would give user yet more control. Perhaps that is the difference. Move all the implementation out of the class gives the user more flexibility. But is it the flexibility that se wants. (Sorry boost pros uses she above, but men users, women developers, viceversa...just a personal thing) First observation from below ....Obviously the application has a great deal to do with it.! :-) Many more experiments to do ... but ... Interesting debate. regards Andy Little ----------- #include <iostream> template< typename A , typename B > struct multiply_traits; // use traits template< typename A , typename B > struct multiply1{ typedef multiply_traits<A,B> traits; typename traits::result_type operator () (typename traits::first_argument_type a, typename traits::second_argument_type b) { return a * b; } }; //use policy template< typename A , typename B, typename Policy> struct multiply2{ typename Policy::result_type operator () (typename Policy::first_argument_type a, typename Policy::second_argument_type b) { return a * b; } // or Policy ()(a,b); etc if ---> policy }; template<typename T> struct multiply_traits<T,T>{ typedef T result_type; typedef T first_argument_type; typedef T second_argument_type; //operator()(a,b) etc if --->policy }; int main() { multiply1<int,int>::traits::result_type val1 = multiply1<int,int>()(10,10); std::cout << val1 <<'\n'; multiply_traits<int,int>::result_type val2 = multiply2<int,int,multiply_traits<int,int> >()(10,10); std::cout << val2 <<'\n'; }

From: "Andy Little" <andy@servocomm.freeserve.co.uk>
But is it the flexibility that se wants.
^^ I try to use "s/he" for that. "se" just looks like a typo.
#include <iostream> template< typename A , typename B > struct multiply_traits;
// use traits template< typename A , typename B > struct multiply1{
typedef multiply_traits<A,B> traits; typename traits::result_type operator () (typename traits::first_argument_type a, typename traits::second_argument_type b) { return a * b; }
};
template< typename A, typename B > class multiply1 { typedef multiply_traits<A,B> traits; public: typedef typename traits::result_type result_type; typedef typename traits::first_argument_type first_argument_type; typedef typename traits::second_argument_type second_argument_type; result_type operator()(first_argument_type a, second_argument_type b) { return a * b; } };
//use policy template< typename A , typename B, typename Policy> struct multiply2{
typename Policy::result_type operator () (typename Policy::first_argument_type a, typename Policy::second_argument_type b) { return a * b; }
// or Policy ()(a,b); etc if ---> policy
};
template< typename A, typename B, class Policy > struct multiply2 : Policy { };
template<typename T> struct multiply_traits<T,T>{ typedef T result_type; typedef T first_argument_type; typedef T second_argument_type; //operator()(a,b) etc if --->policy };
int main() { multiply1<int,int>::traits::result_type val1
multiply1<int,int>::result_type val1
= multiply1<int,int>()(10,10); std::cout << val1 <<'\n';
multiply_traits<int,int>::result_type val2 = multiply2<int,int,multiply_traits<int,int> >()(10,10);
typedef multiply2< int, int, multiply_traits< int, int > > m2; m2::result_type val2(m2()(10, 10));
std::cout << val2 <<'\n'; }
-- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

From: "Andy Little" <andy@servocomm.freeserve.co.uk>
But the root of the problem/thread is exactly what is a trait , or traits and what is a policy. ie to try to come up with an ambiguous specification of the word trait ,traits and policy in a C++ context.
I'd prefer unambiguous definitions or specifications, if you please. ;-)
A trait for an entity is used to describe a feature of the entity, usually by parameterising the entity or some type involved in the entity via a traits mechanism.
I'm sure you meant the right thing, but you've stated what parameterizes what backwards.
(The traits mechanism associates an entity (usually a type) with a particular family of traits ).
I've always thought of it the other way around, but the effect is the same. That is, I've always thought of it as associated the set of traits with the entity.
A policy customises (part of) an entity, usually by providing an (alternative) implementation of (some) functionality of the entity.
I don't agree with how you're characterizing this. A policy provides the implementation -- informational, behavioral, or both -- and, by substitution, can affect the entity.
non UDT examples:
sizeof // has characteristics of a trait. Useful but cant change it
Right.
atexit // has characteristics of a policy. Usually has a default functionality but can customise it
Since you can't change it, it isn't a policy. You can either take advantage of the functionality or not. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
Absolutely not. A key trait of traits is that they're non-intrusive. They create an association with that can be defined *after* the type argument is defined.
Surely a trait is *part of the *definition* * of an *entity* in a wider sense.
I think I just quite definitively disagreed with that assertion already ;^) -- Dave Abrahams Boost Consulting www.boost-consulting.com

David A. wrote:
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
Absolutely not. A key trait of traits is that they're non-intrusive. They create an association with that can be defined *after* the type argument is defined.
Surely a trait is *part of the *definition* * of an *entity* in a wider sense.
I think I just quite definitively disagreed with that assertion already ;^)
Would you disagree with Andy even if that "wider sense" was a GP concept? I agree with Andy under that interpretation, a trait defines the local neighborhood of a concept and its models. /David

"David Bergman" <davidb@home.se> wrote
David A. wrote:
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
[snip]
Surely a trait is *part of the *definition* * of an *entity* in a wider sense.
I think I just quite definitively disagreed with that assertion already ;^)
Would you disagree with Andy even if that "wider sense" was a GP concept?
I guess that David Abrahams is taking me to task on use of the word 'entity' which is defined in the standard (3-3). I wont claim that I was using the term in the sense it is defined there, though it fits. I tried this with the much maligned basic string: struct Dummy_traits{}; int main() { // " definition of an entity " std::basic_string<char,Dummy_traits> str1; } I didnt get very far at least in VC7.1. (One could argue that Dummy_traits is a policy rather than a trait, which seems to be becoming the consensus on this thread.)
I agree with Andy under that interpretation, a trait defines the local neighborhood of a concept and its models.
That phrase "a trait defines the local neighborhood of a concept and its models.",sounds impressive, though I dont quite understand it. Is there more detail on this? ( IMO Concepts Are the next big thing for C++. C++ evolved from C on strong types. And the next generation of C++ will evolve based on Concepts. But crucially I have a very vague notion of what they are.) A concept requires enforcing constraints . Could it be that traits and policies are inextricably linked with Concepts, providing some sort of 'building block' or modularity, scaleabiliy and so on.? BTW replace the word 'traits' by 'features' and it makes more sense to me. traits is a very weak word for anything ;-) regards Andy Little

"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
"David Bergman" <davidb@home.se> wrote
David A. wrote:
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
[snip]
Surely a trait is *part of the *definition* * of an *entity* in a wider sense.
I think I just quite definitively disagreed with that assertion already ;^)
Would you disagree with Andy even if that "wider sense" was a GP concept?
I guess that David Abrahams is taking me to task on use of the word 'entity' which is defined in the standard (3-3).
No, I'm not. Just read the words I wrote. I simply reject the idea that a trait specialization is part of the definition of the type(s) it applies to. Mssrs Little and Bergman seem to want me to mean something else, or to qualify my statement so that I "agree in a wider sense". I mean what I said: I disagree with the statement in any sense. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
"David Bergman" <davidb@home.se> wrote
David A. wrote:
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
[snip]
Surely a trait is *part of the *definition* * of an *entity* in a wider sense.
I think I just quite definitively disagreed with that assertion already ;^)
Would you disagree with Andy even if that "wider sense" was a GP concept?
I guess that David Abrahams is taking me to task on use of the word 'entity' which is defined in the standard (3-3).
No, I'm not. Just read the words I wrote. I simply reject the idea that a trait specialization is part of the definition of the type(s) it applies to.
hmm ..From the latest qualifications of your objections above I now assume you are seeing this. struct traits<T> { ... }; Where traits is the subject, traits<T> is Not part of T's definition. But we have been discussing numeric::converter and std::basic_string and differences between traits and policies... I have been seeing this : template <typename T> struct T1{ typedef traits<T> arg_traits; }; Where T1 is the subject, traits<T> Is part of T1's definition. Also see standard 21-2 relating to strings. " <strings> ..need a set of related types... to complete the definition of their semantics". ----------- The traits or policy discussion seems to boil down to this: In T1 above arg_traits is not user modifiable, However template <typename T,typename P> struct T2{ typedef P arg_traits; }; arg_traits in T2 is user-modifiable. traits<T> is a traits-class, but traits<T> could theoretically be used in T2, in which case it would be regarded as implementing a policy. To implement various policies one can define different traits-classes on the same type, however they might then be best referred to as policy-classes. Use of traits<T> in T1 could also be regarded as a policy, but an immutable one. Based on that one could say that a policy is implemented, simply the Use of a traits-class or a policy-class. The term policy being useful only if the policy is modifiable. regards Andy Little

From: "Andy Little" <andy@servocomm.freeserve.co.uk>
"David Abrahams" <dave@boost-consulting.com> wrote
I simply reject the idea that a trait specialization is part of the definition of the type(s) it applies to.
hmm ..From the latest qualifications of your objections above I now assume you are seeing this.
struct traits<T> { ... }; Where traits is the subject, traits<T> is Not part of T's definition.
But we have been discussing numeric::converter and std::basic_string and differences between traits and policies... I have been seeing this :
template <typename T> struct T1{ typedef traits<T> arg_traits; }; Where T1 is the subject, traits<T> Is part of T1's definition. Also see standard 21-2 relating to strings. " <strings> ..need a set of related types... to complete the definition of their semantics".
I see this: template <typename T> class T3 { }; That is, "traits<T>" isn't part of the interface of T3 specifically, though nested types in it could be. I see traits<T> as an implementation detail injected from the scope where traits<T> is specialized.
The traits or policy discussion seems to boil down to this:
In T1 above arg_traits is not user modifiable, However
template <typename T,typename P> struct T2{ typedef P arg_traits; };
arg_traits in T2 is user-modifiable. traits<T> is a traits-class, but traits<T> could theoretically be used in T2, in which case it would be regarded as implementing a policy. To implement various policies one can define different traits-classes on the same type, however they might then be ^^^^^^^^^^^^^^ In which case, they aren't traits classes to me.
best referred to as policy-classes. Use of traits<T> in T1 could also be regarded as a policy, but an immutable one. Based on that one could say that a policy is implemented, simply the Use of a traits-class or a policy-class. The term policy being useful only if the policy is modifiable.
Yes, but it is equally important, in my mind, that a traits class has a well-known, ubiquitous name. Anywhere you want a particular trait or set of traits for a type T, you always use the same traits class, xxx<T>. The name of a policy is valuable when selecting it from among the set of available policies and to clarify intent in a specialization, but in use, its alias -- the template parameter name -- is important. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Rob Stewart" <stewart@sig.com> wrote
From: "Andy Little" <andy@servocomm.freeserve.co.uk>
I see this:
template <typename T> class T3 { };
That is, "traits<T>" isn't part of the interface of T3 specifically, though nested types in it could be. I see traits<T> as an implementation detail injected from the scope where traits<T> is specialized.
Yes I see what you mean, a typedef is not a very good example of Use of a traits-class by another class. Perhaps more like this: template<typename T> struct adjust_traits; template <typename T> class adjust{ public: typename adjust_traits<T>::feedback_type operator() (typename adjust_traits<T>::output_type const& out ); }; class brightness; class roll_rate; template <> class adjust<brightness>; template<> class adjust<roll_rate>; ( BTW your other post in this thread I am pretty much in agreement with. One point worth making. Perhaps I should use the term *traits-class*, rather than *trait* or *traits*.I guess a trait is a member of a traits-class and traits are members of a traits-class. I have not been following that advice...but meanwhile this thread has cleared up some foggy ideas .. so it has been very helpful to me. regards Andy Little
The traits or policy discussion seems to boil down to this:
In T1 above arg_traits is not user modifiable, However
template <typename T,typename P> struct T2{ typedef P arg_traits; };
arg_traits in T2 is user-modifiable. traits<T> is a traits-class, but traits<T> could theoretically be used in T2, in which case it would be regarded as implementing a policy. To implement various policies one can define different traits-classes on the same type, however they might
then be
^^^^^^^^^^^^^^ In which case, they aren't traits classes to me.
best referred to as policy-classes. Use of traits<T> in T1 could also be regarded as a policy, but an immutable one. Based on that one could say
that
a policy is implemented, simply the Use of a traits-class or a policy-class. The term policy being useful only if the policy is modifiable.
Yes, but it is equally important, in my mind, that a traits class has a well-known, ubiquitous name. Anywhere you want a particular trait or set of traits for a type T, you always use the same traits class, xxx<T>. The name of a policy is valuable when selecting it from among the set of available policies and to clarify intent in a specialization, but in use, its alias -- the template parameter name -- is important.
-- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer; _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Policies must be orthogonal between themselves, but not neccesarily w.r.t the primary type(s). In fact, many common policies (from common policy-based designs) are not.
An example?
If this were not a policy, users would be stuck with the definition of the default traits class. I agree that this opens a window to all sort of problems in case a user plugs in an invalid traits, but I think that should not constitute a reason for fixing the traits into the converter. As always, "trust the programmer"
So again Trait is not a Policy and let's not mix them
I disagree. A trait can _function_ as a policy IMO.
Well, I do follow your arguments but I'm still unconvinced. A traits is type-specific, yes, but not necessarily _unique_. You see it as unique, but why would it has to be like that? It seems that that fundamental point of your argument is that traits are uniquely defined by a type, and not just a type decoration. If this were true, then I would agree, but I don't see why a type can't have a set of "compatible" traits.
Let's get back to the converter class. Do you invision somebody do something like this: struct myInt {...}the_int; struct myFloat {}; a.cpp template<> conversion_traits<myInt,myFloat> { }; boost::numeric_cast<myFloat>( the_int ); b.cpp template<> conversion_traits<myInt,myFloat> { }; boost::numeric_cast<myFloat>( the_int ); And do you think it would be good idea? How definitions in a.cpp and b.cpp could differ? Gennadiy.
participants (11)
-
Andy Little
-
David Abrahams
-
David Bergman
-
Fernando Cacciola
-
Gennadiy Rozental
-
Jonathan Turkanis
-
Mark Rodgers
-
Peter Dimov
-
Rob Stewart
-
Robert Bell
-
Rozental, Gennadiy