【问题标题】:Can concept checking be delayed till class instantiation in C++?概念检查可以延迟到 C++ 中的类实例化吗?
【发布时间】:2021-07-28 07:23:49
【问题描述】:

加速编译的一种常见做法是只声明类而不是给出它们的完整定义,例如

struct A;
template<typename T> struct B;
using C = B<A>;

如果有人喜欢在模板类中使用 C++20 概念,那么代码如下

#include <concepts>
struct A;
template<std::destructible T> struct B;
using C = B<A>;

会导致错误:

error: template constraint failure for 'template<class T>  requires  destructible<T> struct B'
     | using C = B<A>;

是否有可能以某种方式延迟概念检查的时刻,直到 B&lt;A&gt; 真正使用/实例化?如果不是,那么通过强制包含以前隐藏的类定义,概念似乎会显着减慢某些程序的编译速度。

【问题讨论】:

  • 用信息(如概念、继承等)转发声明会很好。
  • static_assert in B 而不是它的概念:/
  • 这基本上会破坏概念的目的,即及早报告错误。
  • 如果可能的话,我可以看到它会导致一些病态的情况。你可以用不完整的类型做事情(C*C&amp; 甚至C foo( C ); 都是有效的)。如果编译器没有当场检查它,你最终可能会得到大量引用不存在的类型的代码。好像错了。
  • 概念决定专业化是否存在,而不是是否可以完成。在许多情况下,使用不完整的类型,然后当概念还没有发挥作用时就会出现问题

标签: c++ c++20 c++-concepts


【解决方案1】:

这就是你转发声明的方式。

struct A;
template<class T> struct B;
using C = B<A>;

保留这个。在B.h

#include <concepts>
template<class T> struct B;
// or
template<class T> struct B
{
  static_assert( std::destructible<T> );
};

template<std::destructible T>
struct B<T> {
};

专业。保留基址 B&lt;T&gt; 未定义。

现在,您得到的错误不会“及早”检查,而是会在稍后发生。因此,将 T 传递给 B&lt;&gt; 不会以 SFINAE 友好的方式进行检查。

但这基本上是你要求不要在你的问题中发生的事情。

请注意,static_assert 可能会在标准的某些读数下使您的程序格式错误,不需要诊断。基本上所有特化(包括基础特化)都必须有一个有效的实例化,而另一个特化的模式匹配使这成为不可能。

但实际上我认为您只会收到一条错误消息。

【讨论】:

  • 谢谢,它工作!唯一令人讨厌的是,错误将是关于incomplete type Bgcc.godbolt.org/z/naWe6cbxf
  • @Fedor 是的。添加{ static_assert( std::destructible&lt;T&gt; ); }; 作为基本专业化的实现,为最终用户提供一点提示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 2021-08-29
  • 2016-06-10
  • 2013-06-06
  • 1970-01-01
  • 2011-11-19
相关资源
最近更新 更多