【问题标题】:Expecting different types depending of point of instantiation根据实例化点期望不同的类型
【发布时间】:2019-02-15 07:30:26
【问题描述】:

我希望以下是不正确的 NDR,但似乎不是 :-(

#include <type_traits>

template <typename T, typename Enabler = void>
struct is_complete : std::false_type {};

template <typename T>
struct is_complete<T, std::void_t<decltype(sizeof(T) != 0)>> : std::true_type {};

class X;

static_assert(!is_complete<X>::type{}); // incomplete type

class X {};

static_assert(!is_complete<X>::type{}); // complete, but already instantiated

Demo

注意:假设 sizeof(T) != 0 对完整性特征有效(因为没有类型可以有 sizeof(T) == 0,使用其他常量将强制为特征找到更好的名称 :-))

它是Is a specialization implicitly instantiated if it has already been implicitly instantiated? 代码的变体,其中程序已被声明为格式错误的程序,不需要诊断 (NDR),因为 方法 is_complete_helper&lt;X&gt;::test&lt;X&gt; 有 2 个不同的含义取决于实例化点。

似乎接近使程序格式错误的参考,但据我了解并非如此:

在假设的实例化中对这种构造的解释不同于在模板的任何实际实例化中对相应构造的解释。

函数模板、成员函数模板或类模板的成员函数或静态数据成员的特化可以在翻译单元内具有多个实例化点,并且除了上述实例化点之外,对于在翻译单元内具有实例化点的任何此类特化,翻译单元的结尾也被视为实例化点。类模板的特化在翻译单元内最多有一个实例化点。任何模板的特化都可能在多个翻译单元中具有实例化点。如果根据单一定义规则,两个不同的实例化点赋予模板特化不同的含义,则程序是非良构的,不需要诊断。

我错了?或者不幸的是,这个程序是正确的。

【问题讨论】:

  • 我相信thisthis 的组合可以解决您的问题

标签: c++ templates language-lawyer template-instantiation


【解决方案1】:

我希望以下是不正确的 NDR,但似乎不是 :-(

您不能将程序编译(并运行)这一事实作为它不是非良构 NDR 的证据。就像你不能使用看似有效的程序输出来证明它没有表现出未定义的行为一样。

也就是说,这里的相关规则是[temp.point]/8:

类模板的特化在翻译单元内最多有一个实例化点。任何模板的特化都可能在多个翻译单元中具有实例化点。如果根据单一定义规则,两个不同的实例化点赋予模板特化不同的含义,则程序是非良构的,不需要诊断。

我们只有一个is_complete&lt;X&gt; 的实例化点:就在第一个static_assert 之前。所以,这“很好”——它可以说是令人困惑和糟糕的,但它是格式良好的。

但是,如果我们将其拆分:

// a.cpp
struct X;
static_assert(!is_complete<X>::value);

// b.cpp
struct X { };
static_assert(is_complete<X>::value);

现在这是格式错误的,不需要诊断。


注意,您不需要sizeof(T) != 0。只需sizeof(T) 就可以了。你不能接受不完整类型的sizeof,所以你只需要检查sizeof(T) 是一个有效的表达式。

【讨论】:

  • 对。我一时糊涂了:)
  • 我的 "似乎不是" 主要是由于链接问题的讨论,实际上编译器不能用于 NDR 证明 ;-) 。遗憾的是代码是正确的:-(,尤其是当小的“无辜”变化使其格式错误时(例如明确使用静态数据成员value 而不是bool_constant 的继承)。
猜你喜欢
  • 2017-09-07
  • 2011-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多