lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi] enable_if boost to std rosetta stone


From: Greg Chicares
Subject: [lmi] enable_if boost to std rosetta stone
Date: Sun, 22 Jan 2017 20:46:47 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.6.0

I haven't found a guide for boost to C++11 or C++14 migration online
that covers enable_if in detail, so let me try to write one.

We have this function (and a throwing disable_if mate, not shown)
that we would like to modernize:

template<typename X, typename Y>
inline Y sfinae_cast
    (X const& x
    ,typename boost::enable_if<std::is_same<X,Y> >::type* = nullptr
    )
{
    return x;
}

If we include
    #include <boost/utility/enable_if.hpp>
    #include <type_traits>
as appropriate, then the following alternative lines seem to be
equivalent, given a C++11 or C++14 compiler:

    ,typename boost::enable_if<std::is_same<X,Y> >::type* = nullptr     // boost
    ,typename std::enable_if<std::is_same<X,Y>::value>::type* = nullptr // C++11
    ,typename std::enable_if_t<std::is_same<X,Y>::value>* = nullptr     // C++14

The differences are clearer if we align identical parts vertically
(use a monospace font):

    ,typename boost::enable_if  <std::is_same<X,Y>       >::type* = nullptr // 
boost
    ,typename   std::enable_if  <std::is_same<X,Y>::value>::type* = nullptr // 
C++11
    ,typename   std::enable_if_t<std::is_same<X,Y>::value>*       = nullptr // 
C++14

Conclusions: C++11 standardized boost::enable_if_c as std::enable_if;
and boost::enable_if allows eliding "::value", while C++14 OTOH adds
std::enable_if_t, which elides "::type" instead.

std::enable_if_t could be used with a C++11 compiler by adding this:

#if __cplusplus <= 201103l
    namespace std
    {
    template<bool B, typename T = void>
    using enable_if_t = typename enable_if<B,T>::type;
    }
#endif // __cplusplus <= 201103l

but that's a lot of work to save four characters per use.

The boost syntax could be used (without boost) by adding this and
removing "boost::":

    template<typename Condition, typename T = void>
    struct enable_if : public std::enable_if<Condition::value,T> {};

which makes migration simple at the cost of future comprehensibility.

Can't we get rid of both "::value" (as boost::enable_if does) and
"::type" (as C++14 std::enable_if_t does) at the same time? I'm
guessing that we can't. I tried combining the immediately preceding
template struct enable_if with the C++14 alias, as follows:

    // This doesn't work as desired.
    template<typename Condition, typename T = void>
    using enable_if_t = typename enable_if<Condition,T>::type;

but gcc-4.9.1 said:

error: expected nested-name-specifier
     ,typename enable_if_t<std::is_same<X,Y> >* = nullptr
               ^
error: expected unqualified-id before '*' token
     ,typename enable_if_t<std::is_same<X,Y> >* = nullptr
                                              ^
error: expected ')' before '*' token
error: expected initializer before '*' token

and my vague impression is that I removed so much that there's
nothing left for SFINAE to chew on.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]