1

Is there a portable way to implement std::is_constructible using concepts without STL using requires expression or template metaprogramming only?

Consider this code:

template <class T, class... Args>
struct is_constructible
    : std::bool_constant<requires {
      new T(std::declval<Args>()...);
    }> {
};

It works fine for other data types except for references because one can't new a reference type.

// Test cases
auto main() -> int {
  static_assert(is_constructible<int>::value);
  static_assert(is_constructible<int, int>::value);
  static_assert(is_constructible<int, float>::value);
  static_assert(!is_constructible<int, int *>::value);
  static_assert(is_constructible<int &, int &>::value);
  static_assert(is_constructible<int &&, int &&>::value);
  static_assert(!is_constructible<void, void>::value);
  static_assert(!is_constructible<int(), int()>::value);
  static_assert(is_constructible<int (*)(), int()>::value);
  static_assert(!is_constructible<intptr_t, int *>::value);
  static_assert(!is_constructible<int &, float &>::value);

  static_assert(std::is_constructible<int>::value);
  static_assert(std::is_constructible<int, int>::value);
  static_assert(std::is_constructible<int, float>::value);
  static_assert(!std::is_constructible<int, int *>::value);
  static_assert(std::is_constructible<int &, int &>::value);
  static_assert(std::is_constructible<int &&, int &&>::value);
  static_assert(!std::is_constructible<void, void>::value);
  static_assert(!std::is_constructible<int(), int()>::value);
  static_assert(std::is_constructible<int (*)(), int()>::value);
  static_assert(!std::is_constructible<intptr_t, int *>::value);
  static_assert(!std::is_constructible<int &, float &>::value);
  
  return {};
}
  • 2
    There's already a standard library concept for this [`std::default_initializable`](https://en.cppreference.com/w/cpp/concepts/default_initializable). It's just a different name then the type trait. EDIT: wait! I think you're looking for [`std::constructible_from`](https://en.cppreference.com/w/cpp/concepts/constructible_from). – JHBonarius Jan 24 '22 at 15:51
  • I don't think the approach using `new` is sufficient. A standard-conform `std::is_constructible` should check that an imagined declaration `T obj(declval()...);` is well-formed. That should include a check for usability of the destructor which `new` doesn't require. – user17732522 Jan 24 '22 at 15:54
  • I know brother, I know. I have to implement it as a practice question. – Mansoor Ahmed Memon Jan 24 '22 at 15:55
  • 1
    ?? Just copy the cpp reference code then?? – JHBonarius Jan 24 '22 at 15:57
  • [lol](https://i.kym-cdn.com/entries/icons/original/000/028/986/scropio.jpg) The implementation uses `std::constructible_from` which in turn uses `std::is_constructible` which does not provide any implementation. @JHBonarius – Mansoor Ahmed Memon Jan 24 '22 at 16:06
  • I have updated my question. – Mansoor Ahmed Memon Jan 24 '22 at 16:11

1 Answers1

7

No. Certainly not "cleanly and nicely".

In fact, early proposals during the standardization process attempted to implement constructible_from using requires expressions, but there were so many corner cases that we gave up and specified it in terms of the type trait instead.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • So, how can we implement the type trait? As far as I know libc++ uses `__is_constructible` in its implementation. – Mansoor Ahmed Memon Jan 24 '22 at 16:09
  • @MansoorAhmedMemon It may not be possible or possible in an efficient manner to implement `std::is_constructible` without a compiler built-in, which is probably why the standard library implementations use one. – user17732522 Jan 24 '22 at 16:41
  • Thanks! Is `__is_constructible` portable tho? – Mansoor Ahmed Memon Jan 24 '22 at 16:50
  • "Is __is_constructible portable" No. – n. m. could be an AI Jan 24 '22 at 16:52
  • @MansoorAhmedMemon The standard library is poorly named. It is not a library in a normal sense; it isn't on top of language features. It is an interface to language features, some of which are implemented (partly or mostly) in-language. – Yakk - Adam Nevraumont Jan 24 '22 at 16:56
  • @user17732522 "*It may not be possible or possible in an efficient manner to implement std::is_constructible without a compiler built-in*" I'm intrigued to ask why though, where would I get to read the discussions (if any)? – Dean Seo Aug 09 '23 at 16:30
  • 1
    @DeanSeo I am not saying that it is definitively impossible, just that this is a possibility. But even if it is possible then, as this answer is saying, there will be so many corner cases to consider that implementation without intrinsic will become infeasible or at least too cumbersome. See also for example the answer and comments [here](https://stackoverflow.com/questions/40439909/c98-03-stdis-constructible-implementation). – user17732522 Aug 09 '23 at 18:05