Boost logo

Boost Users :

Subject: Re: [Boost-users] [MPL] implementing a "trait"?
From: Wouter van Ooijen (wouter_at_[hidden])
Date: 2014-02-04 13:52:19


John M. Dlugosz schreef op 04-Feb-14 7:03 PM:
> I want to mark certain types as being of a category of my invention
> (e.g. is_pretty), for purposes of using enable_if in the same manner
> is standard type traits such as is_arithmetic etc.
>
> The trait will be false by default, and I'd declare something to
> nominate types that should be seen to have that trait. I want it to
> follow inheritance; if B has been declared to be in my category, and C
> is derived from B, then C will also be in that category without
> needing to do anything more (though some way to turn it _off_ would be
> available).

I use

    typedef void has_some_interface;

inside the class to identify that a class implements some interface. I
could write out a global test template and specialization to do
facilitate the checking, but I prefer the macro

    #define ASSERT_PROVIDES_INTERFACE( T, V ) \
       template< class t, class x = void > struct V \
          { static constexpr bool value = false; }; \
       template< class t > struct V< t, typename t::V > \
          { static constexpr bool value = true; }; \
       static_assert( \
          V< T >::value, \
          "the " #T " template argument doesn't provide " #V \
       );

(the \'s line up in a non-proporitionally font) which writes them
'locally'. Use it like this:

struct implements_some_interface {
    typedef void has_some_interface;
    . . .
};

template< class t > class uses_some_interface {
    ASSERT_PROVIDES_INTERFACE( t, some_interface );
    . . .
};

The error message issued by GCC when the feature id type is not provided
is reasonably close to the top of the error list.

In practice I write the identification type in an 'archetype' class that
serves to identify the interface elements that an real implementation
must provide (sort of an abstract base class, but for compile-time
inheritance):

struct char_out_channel_archetype {
    typedef void has_char_out_channel;
    static void put( char c );
};
struct char_in_channel_archetype {
    typedef void has_char_in_channel;
    static char get( );
};

struct uart : public char_out_channel_archetype, public
char_in_channel_archetype {
    static void put( char c ){ . . . }
    static char get(){ . . . }
};

A pity that I can't use 'override' to make sure that the implementations
realy override a declaration in a base class, that works only for
non-static methods. (WHY??)

Wouter van Ooijen


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net