Boost logo

Boost :

Subject: Re: [boost] [Review] GGL review starts today, November 5th
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2009-11-08 04:31:48


Hi,
this is not a review.

Note that I have just read the introduction of the documentation and I find the it quite clear.

Some words about SNIFAE and partial specialization:
At the end of the introduction you say that

>This SFINAE:
>* can be done on functions but not on structs (meta-functions). So the coordinate_type meta-function would still have to use tag dispatching"

First for structs (meta-functions) you can apply partial template specialization, so no need of SFINAE. Even if you neded SFINAE, and if I'm not wrong enable_if can also be applied to structs. From enable_if docummentation "
Enabling template class specializations
Class template specializations can be enabled or disabled with enable_if. One extra template parameter needs to be added for the enabler expressions. This parameter has the default value void. For example:
template <class T, class Enable = void>
class A { ... };

template <class T>
class A<T, typename enable_if<is_integral<T> >::type> { ... };

template <class T>
class A<T, typename enable_if<is_float<T> >::type> { ... };"
>*gives often compiler troubles and headaches: if a user makes an error somewhere, the compiler will not select any of the methods, and/or it will give completely incomprehensible error listings, just because of this SFINAE"

I thought that this was and advantage not a liability. The message is short: method not found.
What errors do you get when a user makes an error somewhere with tag dispatching? Are they clearer?

> * does not support partial specializations because it is a function. The tag-dispatching function is of course also not supporting that, but it forwards its call to the dispatch struct where partial specializations (and member template functions) are possible. The SFINAE could do that as well but then: why not just add one tag more and have tag dispatching instead?"

Could you clarify which is the tag you add?

> * is a trick to deceive the compiler. "As a language behavior it was designed to avoid programs becoming ill-formed" (http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error), while tag dispatching is based on specialization, a core feature of C++
>* looks more ugly

You know that this is a matter of taste, and the way you do force the user to share your taste.

> *is simply not necessary because we have tag dispatching :-)

Not necessary do not meens that it is not good.

Recently I have added some stuff to take care of ADL in the Boost.Conversion library base on the Boost.Swap library. The idea been to define a function that calls an internal function introdicing the default behavior by ADL. Thus when the user has provided some functions found by ADL they will take precedence as more specific. When not found the introduced default behavion take place.

Next follows how I have defined convert_to:

namespace boost {
    // trick to ensure specialization is always possible
    namespace dummy {
        template <typename T> struct base_tag {};
        template <typename T> struct type_tag : public base_tag<T> {};
    }
    // default behavior ussin gthe specialized tag type_tag
    namespace conversion {
        namespace partial_specialization_workaround {
            template < typename To, typename From >
            struct convert_to {
                inline static To apply(const From& val)
                {
                    return To(val);
                }
            };
        }
        
        template < typename To, typename From >
        To convert_to(const From& val, dummy::type_tag<To> const&) {
            return conversion::partial_specialization_workaround::convert_to<To,From>::apply(val);
        }
    }
    // specialized implementation
    namespace conversion_impl {
            template <typename Target, typename Source>
            Target convert_to_impl(Source const& from) {
                using namespace boost::conversion;
                //use boost::conversion::convert_to if ADL fails
                return convert_to(from, boost::dummy::type_tag<Target>());
            }
    }
    // generic function calling to the ADL introduction
    template <typename Target, typename Source>
    Target convert_to(Source const& from, boost::dummy::base_tag<Target> const& p=boost::dummy::base_tag<Target>()) {
        return conversion_impl::convert_to_impl<Target>(from);
    }
}

Note that using the dummy trick we ensure that there are no infinite cycles.
The default behavior could correspond to what you have already done.

If there is nothing wrong on my design, do you think that this could be also applied to the GGL library at least for the concepts?

Good work anyway :)

Best,
Vicente


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