cho*_*ger 6 c++ standards types llvm
我今天正在调试一个失败的clang构建.那个构建基本上破了,因为is_default_constructible评估为false.经过几个小时的平分问题后,我将问题减少到最小的情况:
#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!");
Run Code Online (Sandbox Code Playgroud)
上面的例子用g ++ 6.3和7.0编译得很好.它在clang ++ 4.0.0和3.9.1中失败了 - 静态断言仅在非常具体的构造中失败,但它仍然破坏了我们的构建.正如您可以自己尝试一样,一些最小的更改可以解决问题(例如,评论其中一条提到的行).结果看起来有点武断.
我想知道的是,clang中的明显错误是否实际上是一个错误或一些未定义的行为.实际上,这部分语言的定义有多好?
我也很感激有关如何调试这些问题的任何建议:有没有一种好方法可以从clang中获取一些信息,为什么它确实认为Foo不是默认构造?
最后,如果你们中的任何人都可以访问(标准兼容的)第三个C++实现并且可以报告结果,那将是非常好的.
小智 1
在外部类完成之前(即在外部类定义的分号处),不会实例化嵌套类的默认数据成员初始值设定项。当使用类型特征在嵌套类完成时(即在其定义之后)但在外部类完成之前查询嵌套类时,这会导致奇怪的后果。
您可以通过将 Foo 移到 B 之外来解决此问题。