如何避免这种讨厌的概念陷阱取决于顺序

问题描述

以下代码取决于该概念是在该类之前 还是 之后定义的。目的是检查是否可以从Quantity构造T。我已将其删除,仅显示了复制构造的测试。

template <typename T>
concept is_compatible = requires( T & t ) { Quantity( t ); }; // note: not Quantity<T> !

template <typename T>
class Quantity
{};

class X{};        

int main() 
{

    std::cout << is_compatible<Quantity<X>>;
    std::cout << is_compatible<X>;
}

对于给定的代码,输出为00,而不是预期的10。要获得预期的结果,必须在该类之后的中定义该概念。

我期望上面的代码有两件事之一:

  1. 它只是按预期工作
  2. 编译器会给出警告或错误(以提示我们的错误,如果是错误提示)。用Quantity<T>代替概念中的Quantity会发出编译器错误,因为此时Quantity<T>没有意义。

我不会期望第三个静音选项!可能有一个“很好的理由”,“因为编译器以某种方式工作”,但是我发现这是有缺陷的。

如果行为正确,那么编写此代码的更好方法是什么?

解决方法

可能有一个“很好的理由”,“因为编译器以某种方式工作”,但是我发现这是非常有缺陷的。

没有它,概念就不会有用。您将无法检查依赖于ADL的函数调用表达式是否有效。这对声明对您的概念很满意

namespace ns {
    struct X {};
    void Quantity(X) {}
}

即使在is_compatible之前定义了ns,也会满足要求。

现在,如果您的概念与ADL不相关,并且您的表达式确实打算用作函数样式的强制转换,则只需限定类型(或模板名称)

template <typename T>
concept is_compatible = requires( T & t ) { ::Quantity( t ); };
                                          // ^ -- in the absence of a preceding declaration,error here

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...