c++ - 如何避免这个讨厌的概念陷阱(取决于顺序)
问题描述
以下代码取决于概念是在类之前还是之后定义的。目的是检查 a 是否Quantity
可以从 a 构造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。要获得预期的结果,必须在类之后定义概念。
对于上面的代码,我会期待以下两件事之一:
- 它只是按预期工作
- 编译器给出警告或错误(提示我们的错误,如果它是一个) 请注意,当使用 eg
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
推荐阅读
- reactjs - 在运行时更改 Material UI 反应主题的最佳方式
- apache-spark - 无法加载类 | Spark-提交 Intellij
- r - 突出显示图中斜率最大的多条线
- python-3.x - 无效语法:使用初始排序键自动创建表排序键
- android - Android按钮垂直填充?
- reactjs - 将 flask_restplus 与 react-admin 连接起来
- swift - 带有 PageTabViewStyle 的 TabView 无法正确旋转到横向并返回
- python - 如何管理代码,使代码的所有数据库部分都存储在模块中,前端部分在主代码中
- azure-devops - Azure Devops 中的非活动任务查询
- c - 使用 HAL 的 NUCLEO-F303K8 上的 DMA 不当行为