【问题标题】:std::is_constructible on incomplete types不完整类型上的 std::is_constructible
【发布时间】:2019-09-13 20:06:05
【问题描述】:

我有以下代码:

#include <iostream>

class A;

int main()
{
    std::cout << std::is_constructible<A>::value << std::endl;
}

当我使用GCC 8.3 时,此代码会编译。但是,当我使用Clang 8.0 时,我收到一个编译错误,即不能在类型特征中使用不完整的类型。

哪一个是正确的?我是否可以在不完整的类型上使用is_constructible(预期值为false),还是不允许?

【问题讨论】:

  • 如果A 不是一个完整的类型,is_constructible 将如何确定A 是否可构造?
  • @FrançoisAndrieux:如果A 不完整,我们就无法构造它(A a; 在不完整的类上 A 会导致编译器错误)——这就是它的工作方式我们过去的代码库,但由于未定义的行为,这似乎只是运气。
  • 回复:“我们不能构造它”——类型特征是关于类型的属性。如果std::is_constuctible&lt;A&gt; 根据您包含的标题更改其结果,那将是非常令人不安的。在一个地方它是可构造的,而在另一个地方它不是?
  • @PeteBecker:这是一个我没有考虑过的公平点——最初的用例是一个模板化的class A,它只实例化了特定的参数。然后我们将 SFINAE 与 std::is_constructible 一起使用,以便只允许某些类型的类型通过。这很容易通过显式实例化默认的class A 来正确完成,其中显式删除了构造函数(这是我所做的),但思考过程是从那个角度出发的。没有考虑(应该很明显的)“实际存在的前向声明类”角度......

标签: c++ c++11 language-lawyer


【解决方案1】:

行为未定义。

[meta.unary.prop]

template <class T, class... Args> struct is_constructible;

T和参数包Args中的所有类型都是完整的类型, (可能是 cv 限定的)void 或未知边界的数组。

That's a precondition 的元函数。您的代码违反的合同。 libc++ 很慷慨地通知您。


请注意,将前提条件放在那里并使其未定义是有原因的。一个模板的两个实例化点具有不同含义的程序是ill-formed NDR。唯一明智的做法是需求完整类型。毕竟,那是特质最有用的时候。

【讨论】:

    【解决方案2】:

    您的代码会导致未定义的行为。

    Cppreference 状态:

    template< class T, class... Args > struct is_constructible;

    T 和参数包 Args 中的所有类型均应为完整类型、(可能是 cv 限定的)void 或未知边界数组。 否则,行为未定义。

    【讨论】:

      【解决方案3】:

      您的代码具有未定义的行为。根据[meta.unary.prop] table 47 std::is_constructible 要求

      T 和模板参数包Args 中的所有类型应为完整类型cv void 或未知范围的数组。

      强调我的

      【讨论】:

        猜你喜欢
        • 2014-07-21
        • 1970-01-01
        • 1970-01-01
        • 2018-11-08
        • 2018-06-07
        • 2012-05-12
        • 2018-01-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多