I was debugging a failing clang build today. That build essentially broke, because a is_default_constructible
evaluated to false
. I reduced the issue to a minimal case after several hours of bisecting the issue:
#include <type_traits>
#include <string>
namespace A {
// This has been extracted from an old (outdated(?))
// implementation of an optional type
struct empty_t {};
template<class T>
struct o
{
public:
template<class... U,
typename std::enable_if<
std::is_constructible<T, U...>::value,
bool
>::type = false
>
o(empty_t, U&&... u) { }
};
}
struct B
{
struct Foo
{
//Foo () {}; // uncomment this line and it works
bool x = true; // comment this line and it works
};
std::string c; // comment this line and it works, also change to int
A::o<Foo> r; // comment this line and it works
static const bool b;
};
static_assert(
std::is_default_constructible<B::Foo>::value,
"not constructible!");
The example above compiles fine with g++ 6.3 and 7.0. It fails with clang++ 4.0.0 and 3.9.1 - the static assertion fails only in that very specific construction, but it still broke our build. As you can try for yourself, some minimal changes fix the issue (e.g. commenting one of the mentioned lines). The result looks somewhat arbitrary.
What I'd like to know is, whether that apparent bug in clang is actually a bug or some undefined behavior. How well defined is that part of the language, actually?
I would also appreciate any advice on how to debug such issues: Is there a good way to get some info out of clang on why exactly it believes that Foo is not default constructible?
Finally, if anyone of you has access to a (standard compliant) third C++ implementation and could report on the results, that would be very nice.