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.