Boost logo

Boost :

Subject: Re: [boost] traits classes vs. metafunctions
From: Dave Abrahams (dave_at_[hidden])
Date: 2013-03-30 23:57:24


on Wed Mar 06 2013, Stefan Strasser <strasser-AT-uni-bremen.de> wrote:

> Hi everyone,
>
> are there any guidelines for boost libraries on when to use traits
> classes and when to use a metafunction for each member of a would-be
> traits class?

Yeah, use metafunctions :-)

> I've seen both in boost libraries. c++11 uses traits classes
> (iterator_traits, pointer traits, ...), but Abrahams and Gurtovoy [1]
> argue that traits classes ("traits blobs") should be avoided "at all
> costs" because they are an unnecessary concatenation of multiple
> metafunctions into one metafunction with multiple return values.
>
> in practice, this means that if a single 'traits class member' aka
> metafunction result' ought to differ from the defaults, the entire
> traits class has to be reimplemented by the user, not only the
> metafunction whose result ought to differ from the default.
> on the other hand, asking a user to implement 5 or more metafunctions
> is much more tedious than implementing a traits class.

Not having the metafunctions decreases interoperability. Having the
metafunctions and the traits classes increases confusion and clutter.
It's already pretty darned tedious to produce specializations of another
library's templates, because of the namespaces to open/close. I don't
think asking users to provide a traits class offers much convenience
advantage at all. There's usually a better way to get convenience, and
that is to have the metafunctions' default implementations reach into
one of their parameters for their results.

> possibility 1)
>
> template<...> struct property1 : mpl::bool_<...>{};
> template<...> struct property2 : mpl::bool_<...>{};
> template<...> struct property3 : mpl::bool_<...>{};
>
> 2)
>
> template<...>
> struct ..._traits{
> typedef mpl::bool_<...> property1;
> typedef mpl::bool_<...> property2;
> typedef mpl::bool_<...> property3;
> };
>
> you could provide both, but in which "direction"?
> does a traits class refer to metafunctions, or do metafunctions refer
> to a traits class?
>
> a)
>
> template<...>
> struct ..._traits{
> typedef typename property1<...>::type property1;
> typedef typename property2<...>::type property2;
> typedef typename property3<...>::type property3;
> };
>
> b)
>
> template<...> struct property1 : ..._traits<...>::property1{}
> template<...> struct property2 : ..._traits<...>::property2{}
> template<...> struct property3 : ..._traits<...>::property3{}
>
> which is accessed when "calling" the metafunction?

If you think specializing metafunctions is painful, then clearly you
need (b). But I don't think that.

> it seems to me that metafunctions are better for the "caller" and
> traits classes are better for the implementor of the
> traits/metafunctions.

Only if the implementor has would have to implement all or most of the
metafunctions, and then the convenience is only marginal, IMO.

> in my case, the caller is a library and the implementor is the user,
> so you might choose a traits class over metafunctions. but what if a
> new member is added that wasn't there before (like "property4").
> the implementor of an (old) traits class could not have known about
> the new member, so accessing the new member (by the library) will
> result in an error, while a new metafunction "property4" could simply
> return a default.
> should new properties of traits classes only be accessed after making
> sure they exist, using SFINAE?
> there isn't a precedent for this in c++11. only new traits classes
> were introduced, but no new members of already existing traits
> classes.
>
> should metafunctions always be preferred?

IMO unless there's a compelling argument against them, yes.

> why did c++11 choose traits classes over metafunctions, even though
> the concept of a metafunction was introduced in c++11 (<type_traits>).

Because I got lazy and didn't try to educate all the contributors to the
standard and control the design of the standard library in that way.

P.S. Have you seen what they did with enable_if?

-- 
Dave Abrahams

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