【发布时间】:2017-12-04 09:48:51
【问题描述】:
我今天正在调试失败的 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!");
上面的例子在 g++ 6.3 和 7.0 下编译得很好。它在 clang++ 4.0.0 和 3.9.1 中失败 - 静态断言仅在那个非常具体的构造中失败,但它仍然破坏了我们的构建。正如您可以自己尝试的那样,一些最小的更改可以解决问题(例如,评论提到的行之一)。结果看起来有些随意。
我想知道的是,clang 中明显的错误实际上是错误还是某些未定义的行为。实际上,这部分语言的定义有多好?
我也很感激有关如何调试此类问题的任何建议:有没有一种好方法可以从 clang 中获取一些信息,说明为什么它认为 Foo 不是默认可构造的?
最后,如果你们中的任何人都可以访问(符合标准的)第三个 C++ 实现并且可以报告结果,那就太好了。
【问题讨论】:
-
如果你删除
A::o的构造函数,它会在 Clang 中编译。奇怪...我相信 Clang 在这里有问题...