[PATCH] [libc++] Try and prevent evaluation of `is_default_constructible` on tuples default constructor if it is not needed.

Louis Dionne ldionne.2 at gmail.com
Thu Feb 12 07:34:12 PST 2015


In http://reviews.llvm.org/D7569#122353, @EricWF wrote:

> Could you explain why the dependent type trick actually works? I'm
>  unsure as to why clang thinks it can evaluate one set of template
>  arguments but not the other even though it has essentially the same
>  information when evaluating `tuple()`.


Let's take the `pair` example:

  template <class T, class U>
  struct pair {
    template <bool Dummy = true,
      class = typename std::enable_if<
           std::is_default_constructible<T>::value
        && std::is_default_constructible<U>::value
        && Dummy>::type
      >
    constexpr pair() {}
  };

Because `T` and `U` are known when `pair<T, U>` is instantiated, regardless of 
whether the default constructor is instantiated too, the above is equivalent to

  template <class T, class U>
  struct pair {
    static constexpr bool T_is_default_constr = std::is_default_constructible<T>::value;
    static constexpr bool U_is_default_constr = std::is_default_constructible<U>::value;
  
    template <bool Dummy = true,
      class = typename std::enable_if<
           T_is_default_constr
        && U_is_default_constr
        && Dummy>::type
      >
    constexpr pair() {}
  };

So Clang can (and does) instantiate the `is_default_constructible<T>` as soon
as it can, which is as soon as `pair<T, U>` is instantiated. What I wrote for
`std::tuple` would then just be equivalent to:

  template <class ..._Tp>
  struct tuple {
    static constexpr bool _Tp1_is_default_constr = std::is_default_constructible<_Tp1>::value;
                              ...
    static constexpr bool _Tpn_is_default_constr = std::is_default_constructible<_Tpn>::value;
  
    template <bool Dummy = true,
      class = typename std::enable_if<
           _Tp1_is_default_constr && Dummy
        &&            ...
        && _Tpn_is_default_constr && Dummy
      >::type
      >
    constexpr pair() {}
  };

At least, that's my analysis but I could be wrong.

> Also is clang ever going to outsmart this trick and realize

>  `dependent<is_default_constructible<_Tp>, Dummy>` is not actually

>  dependent on anything in this context? (ie on a default constructor)


That's a really good question. I think it could, in theory. That's because
a constructor does not have a name, so it is impossible to call e.g.

  
  tuple<int, char>::tuple</* Dummy = */false>()

Hence, I think in theory the compiler could say "hey you have template 
parameters but it is _impossible_ to specify something else than their 
default value, so let's substitute the parameters now". I'm not sure
what is said about that in the standard though; perhaps someone can
shed light on this?

Louis


http://reviews.llvm.org/D7569

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/






More information about the cfe-commits mailing list