C++20:根据概念验证模板体



C++20引入了一些概念,使我们能够在模板的声明中指定模板参数必须提供某些功能。如果使用不满足约束的类型实例化模板,则编译将在实例化时失败,而不是在编译模板的主体并注意到替换后的无效表达式时失败。

这很好,但它引出了一个问题:有没有一种方法可以让编译器在实例化之前查看模板主体(即将其视为模板,而不是模板的特定实例化),并检查所有涉及模板参数的表达式是否由约束保证存在?

示例:

template<typename T>
concept Fooer = requires(T t)
{
{ t.foo() };
};
template<Fooer F>
void callFoo(F&& fooer)
{
fooer.foo();
}

这个概念使我无法用不支持模板主体中的表达式的类型实例化callFoo。但是,如果我将功能更改为:

template<Fooer F>
void callFoo(F&& fooer)
{
fooer.foo();
fooer.bar();
}

如果我用定义foo(因此满足约束)但不定义bar的类型实例化callFoo,那么这将失败。原则上,该概念应使编译器能够在实例化之前查看此模板并拒绝它,因为它包含表达式fooer.bar(),而约束不能保证其存在。

我认为这样做可能存在向后兼容性问题,尽管如果只使用受约束的参数(而不仅仅是typename/class/等参数)进行验证,那么它应该只影响新代码。

这可能非常有用,因为由此产生的误差可以用来指导约束的设计。编写模板实现,编译(还没有实例化),然后针对每个错误,向约束添加所需的任何要求。或者,在相反的方向上,当遇到错误时,调整实现以仅使用约束提供的内容。

是否有编译器支持启用此类验证的选项,或者是否有计划在任何时候添加此选项?现在或将来进行这种验证是概念规范的一部分吗?

是否有编译器支持启用这种类型验证的选项,或者是否有计划在任何时候添加此选项?现在或将来进行这种验证是概念规范的一部分吗?

无、无和无

您正在寻找的功能称为定义检查。也就是说,编译器根据提供的概念在定义模板时检查模板的定义,如果有任何内容不验证,则会发出错误。例如,Rust特性、Swift协议和Haskell类型类就是这样工作的。

但C++概念并不是这样工作的,而且考虑到C++概念可以是任意表达式,而不是函数签名(就像在其他语言中一样),添加对这种东西的支持似乎完全不可行。

你能做的最好的事情就是用尽可能少地满足你的需求的激进的外来类型(这里的术语是原型)对你的模板进行彻底的单元测试,并抱着最好的希望。

TL;DR:没有

最初的C++11概念的设计包括验证。但当它被放弃时,新版本的设计范围要窄得多。新设计最初建立在constexpr布尔条件之上。添加最终的requires表达式是为了使这些布尔检查更容易编写,并使概念之间的关系更加合理。

但是C++20概念设计的基本原理使得它基本上不可能进行完全验证。即使一个概念完全由原子requires表达式构建而成,也没有办法真正判断一个表达式是否像在requires表达式中那样在代码中使用。

例如,考虑这个概念:

template<typename T, typename U>
concept func_to_u = requires(T const t)
{
{t.func()} -> std::convertible_to<U>;
};

现在,让我们想象一下以下模板:

template<typename T, typename U> requires func_to_u<T, U>
void foo(T const &t)
{
std::optional<U> u(std::in_place, t.func());
}

如果查看std::optional,就会发现in_place_t构造函数不接受U。那么…这是对这个概念的合法使用吗?毕竟,该概念表示,由该概念保护的代码将调用func(),并将结果转换为U。但是这个模板不能做到这一点。

相反,它采用返回类型,实例化由func_to_u保护的而非的模板,并且该模板可以执行它想要的任何操作。现在,这个模板确实执行了对U的转换操作。

因此,一方面,很明显,我们的代码确实符合func_to_u意图。但这只是因为它碰巧将结果传递给了符合func_to_u概念的其他函数。但该模板并不知道它受到convertible_to<U>的限制。

所以。。。编译器应该如何检测这是否正常?失败的触发条件可能在optional的构造函数中。但是构造函数是而不是受概念约束;是我们的外部代码受制于这个概念。因此,编译器基本上必须展开代码使用的每个模板并将概念应用到其中。只是它甚至不会应用整个概念;它将只是应用CCD_ 23部分。

快速做这件事的复杂性逐渐失控。

最新更新