【问题标题】:What is the reason behind instable type traits?不稳定类型特征背后的原因是什么?
【发布时间】: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 在这里有问题...

标签: c++ types llvm standards


【解决方案1】:

嵌套类的默认数据成员初始化器在 outer 类完成之前不会被实例化(即,在外部类定义的分号处)。当嵌套类完成时(即在其定义之后)但在外部类完成之前,使用类型特征查询嵌套类时,这会导致奇怪的后果。

您可以通过将 Foo 移到 B 之外来解决此问题。

【讨论】:

猜你喜欢
  • 2011-06-16
  • 2011-06-20
  • 1970-01-01
  • 2015-08-02
  • 2018-08-31
  • 2020-01-26
  • 2016-03-31
  • 2021-11-01
  • 2010-10-03
相关资源
最近更新 更多