Boost logo

Boost :

Subject: Re: [boost] [type_traits] A partial implementation of boost::is_constructible
From: Paul Fultz II (pfultz2_at_[hidden])
Date: 2016-02-19 13:03:18


On Friday, February 19, 2016 at 1:47:05 AM UTC-6, Andrzej Krzemienski wrote:
>
> I filed a ticket about a potential improvement of type trait
> boost::is_constructible: https://svn.boost.org/trac/boost/ticket/12003
>
> I am solving the following problem. I have a one-argument perfect
> forwarding explicit constructor and want to constrain it only to the cases
> when T is constructible from U:
>
> ```
> template <typename T>
> struct optional
> {
> template <typename U>
> explicit optional(U&& v, ENABLE_IF(is_constructible<T, U&&>))
> {...}
> };
> ```
>
> I cannot afford to use the "fallback" implementation of
> boost::is_constructible (the one that forwards to is_convertible) because
> I
> would be constraint my constructor too much: I would rather leave it
> under-constrained.
>
> I do not need the full implementation of is_constructible (that would need
> variadic templates) because I am only using the two-argument version (and
> I
> suppose my problem is not isolated).
>
> I would like a partial implementation of is_constructible that works
> correctly for two arguments only; and a macro that allows me to test if it
> is available.
>

To implement this properly requires a compiler with expression SFINAE, which
is supported in clang, gcc 4.4 or higher, and partially supported in MSVC
2015. Both MSVC and clang do provide a `__is_constructible` type trait
intrinsic. I am not sure what version of MSVC this was introduced.

Utimately, if you are wanting Boost.Optional to have compatabiliy with
earlier
compiler versions then it will need to fallback on `is_convertible`. For
your
case, `is_constructible` could be implemented something like this:

#if HAS_EXPRESSION_SFINAE
template<int N>
struct holder
{ typedef void type; };

template<class T>
T declval();

template<class T, class U, class=void>
struct is_constructible
: false_type
{};

template<class T, class U>
struct is_constructible<T, U, typename holder<
    sizeof(T(declval<T>()))
>::type>
: true_type
{};

#elif HAS_IS_CONSTRICTIBLE_INTRINSIC

template<class T, class U>
struct is_constructible
: integral_constant<bool, (__is_constructible(T))>
{};

#else

template<class T, class U>
struct is_constructible
: is_convertible<U, T>
{};
#endif

Paul


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