Boost logo

Boost :

From: Andy Little (andy_at_[hidden])
Date: 2004-04-02 15:40:53

"Robert Bell" <belvis_at_[hidden]> wrote in message
> Andy Little wrote:
> > "David Abrahams" <dave_at_[hidden]> wrote in message
> >
> >
> >>"Gennadiy Rozental" <gennadiy.rozental_at_[hidden]> 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.

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';


Boost list run by bdawes at, gregod at, cpdaniel at, john at