Fallback variadic constructor – why does this work?

The issue with your code is that we just instantiated is_constructible in a context where it gets the answer wrong. Any kind of caching in the template code is likely to result in bugs — try printing is_constructible on the same parameters after you call the constructor! It is likely to get it wrong.

Live example of how it can go wrong. Notice it claims C cannot be constructed from an int&, despite having done so on the previous line.

struct C {
  C(const char*, size_t) {}
  template <class... Ts,
    typename = std::enable_if_t<!std::is_constructible<C, Ts&&...>::value>
  >
  C(Ts&&... ) { }
};

int main() {
  int a = 0;
  C x{a};
  std::cout << std::is_constructible<C, int&>{} << '\n';
}

oops.

I suspect this might be an ODR violation — the two definitions of is_constructible have different types at different spots? Or maybe not.

Solution to the original problem that does not have this issue also posted.

Leave a Comment