我开始试验C++20的概念特性,当我意识到可以部分显式地为概念提供模板参数时,我感到非常高兴。我读了cppreference的文章,没有发现其中提到的。
但随后我意识到了一些奇怪的事情:模板参数的规范顺序与我所期望的相反。当提供一个explicite模板参数时,它将替换模板列表中的第二个模板:
#include <concepts>
#include <type_traits>
/// Concept in order to deduce if sth. is base of sth else
template <typename Impl, typename Base> //XXX: here the order of Impl and Base are not
concept Implements = std::is_base_of_v<std::remove_reference_t<Base>, // what I would've expected.
std::remove_reference_t<Impl>>;
/// Example Base class impl
struct BaseExample {};
/// Implementation of BaseExample
struct ImplExample : BaseExample {};
/// Function in which the concept is applied
template <Implements<BaseExample>... Baes> void f(Baes &&... ) {}//} ((void)b, ...); }
int main() {
(void) std::is_base_of_v<BaseExample, std::remove_reference_t<ImplExample &&>>; //< true
(void) std::is_base_of_v<BaseExample, std::remove_reference_t<ImplExample&>>; //< true
f(ImplExample{}, ImplExample{});
}
从我的观点来看,部分提供显式模板参数的可能性是有意义的,因为反对类部分模板规范的论点在这里并不适用,而是使概念更加通用。现在我想知道:
代码可以在这里找到。
编辑后,我检查了三个模板参数指定时的行为。看起来我错误地解释了规范的顺序:第一个参数被‘保留自由’以包含要检查的参数,而显式规范从第二个参数开始。这里可以看到这一点。即使我想出了规范顺序背后的原因,我也会对上面问题的答案非常感兴趣。
是的,部分概念ID确实是一个C++20的东西。第一个参数的特殊状态虽然令人惊讶,但允许使用类似std::constructible_from
这样的情况,它声明为
template<class T,class ...Args>
concept constructible_from=…;
std::constructible_from
是一个类型约束,要求它所引入的任何内容都可以从两个int
参数中构造。但是,它也可以是表达式,在这种情况下,它报告是否可以从int
构造int
(破坏者:true
),但无论参数顺序如何,都存在潜在的混淆。
如果T
必须放在最后,那么就无法使用这样的概念:只有模板参数推导或默认模板参数才能为参数包以外的模板参数提供值,而这两个参数都不适用于这里。
在您链接的论文站点上发布的每一封邮件都包含了标准的最新草案,另外的邮件还包含了关于采用了哪些论文的注释。或者您可以直接访问草稿的存储库(至少如果您喜欢阅读LaTeX的话)。