Boost logo

Boost :

From: Robert Bell (belvis_at_[hidden])
Date: 2004-04-02 17:22:50


Rozental, Gennadiy wrote:
>>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
>>
>> };
>
>
> And give me single example where second design is preferable to first?
>
> Actually I think the best design would look like this:
>
> namespace {
>
> struct multiply_t
> {
> template< typename A , typename B >
> struct sig : multiply_traits<A,B> {};
>
> template< typename A , typename B >
> typename sig<A,B>::result_type
> operator ()( typename sig<A,B>::first_argument_type a,
> typename sig<A,B>::second_argument_type b )
> {
> return a * b;
> }
> } multiply;
>
> }
>
> int main()
> {
> std::cout << multiply( 10, 1.5 ) <<'\n';
>
> MyInt i( 10 )
> std::cout << multiply( i, 10 ) <<'\n';
> }

The problem with your solution is that it arbitrarily restricts the
degrees of freedom a client has, all in the name of "a trait is a trait,
and a policy is a policy."

Suppose I have two contexts in which I need to multiply two unsigned
chars together. In context one, I want the result type to be unsigned
char, because in this context I'm using modulo arithmetic. In context
two, I want the result type to be int, because here I'm using ordinary
arithmetic. It seems pretty easy to me to do this with "multiply2" above
by passing in different policies. Using your solution, I cannot
customize the return type this way.

Bob


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk