[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.
- [lmi] enable_if boost to std rosetta stone,
Greg Chicares <=