【问题标题】:Why is the concept in template template argument not verified?为什么模板模板参数中的概念没有得到验证?
【发布时间】:2021-10-07 20:28:10
【问题描述】:

C++20 允许程序为模板模板参数指定概念。例如,

#include <concepts>

template <typename T> concept Char = std::same_as<T, char>;
template <typename> struct S {};
template <template <Char U> typename T, typename U> T<U> foo() { return {}; }

int main() { foo<S, int>(); }

函数foo 的第一个模板参数应该是一个单参数模板。

概念Char 被定义为只有char 类型为真,因此满足int 的尝试将失败。以上程序仍被所有编译器接受:https://gcc.godbolt.org/z/PaeETh6GP

能否请您解释一下,为什么可以指定模板模板参数中的概念,但仍然会被忽略?

【问题讨论】:

  • 这里只是猜测,但可能出于同样的原因,可以指定内部参数的名称但它被忽略。您可以将这些概念应用于示例中的“第二个”U,它可以按预期工作。另请注意,没有有效实例的模板是格式错误的 NDR。
  • 我的猜测是template &lt;False U&gt; typename T 要求,只要满足False&lt;U&gt;T&lt;U&gt; 就有效,即vacuously true。换句话说,typename U 隐含False U,而False&lt;U&gt; 隐含True&lt;U&gt;Truetypename 的概念对应物)。当TT&lt;U&gt;一样使用时,直接使用T所指的模板(即S),绕过模板模板参数中的False。 (见contravariance
  • 可以简化为that(去掉U)IMO。
  • 参见标准草案中的this 示例。
  • @Fedor 您的示例格式错误,NDR 因为False 永远不会满足。重复的问题不是关于替换失败,而是关于为什么程序格式错误,NDR。这是结束问题的糟糕借口,因为真正的问题与 NDR 无关。以这样一种方式重写问题,使约束只在某些时候得到满足,这样它就不再是病态的了。

标签: c++ c++20 c++-concepts contravariance template-templates


【解决方案1】:

模板(实际)参数匹配模板(正式)参数,如果后者至少与前者一样专业

template &lt;Char&gt; typename Ttemplate &lt;typename&gt; struct S专业化。粗略地说,template &lt;Char&gt; 接受 template &lt;typename&gt; 接受的子集(“至少作为专业”的确切定义实际上相当复杂,但这是第零个近似值)。

这意味着实际参数可以在可以使用形参的所有上下文中使用。也就是说,对于T&lt;K&gt; 有效的任何类型KS&lt;K&gt; 也有效(因为S&lt;K&gt; 对任何K 都有效)。

所以可以用S 代替T

如果你反其道而行之:

template<typename T> concept Any = true; 
template<typename T> concept Char = Any<T> && std::same_as<T, char>;

template<template<Any> class T> void foo();
          
template<Char> struct S { };
          
int main()  
{           
    foo<S>(); 
}

那么这是不正确的,因为(大致)您可以说T&lt;int&gt;,但不能说S&lt;int&gt;。所以S 不是T 的有效替代品。

注意事项:

  1. 为什么我们需要这个永远正确的概念Any?简单地说template &lt;template &lt;typename&gt; typename&gt;有什么问题?嗯,这是因为一个特殊的规则:如果参数根本没有受到约束,那么参数的约束就会被忽略,一切正常。
  2. 为什么写Any&lt;T&gt; &amp;&amp; std::same_as&lt;T, char&gt;;?为了说明一点。实际规则不会评估约束的布尔值,而是将约束作为公式进行比较,其中原子约束用作变量,请参阅here。所以正式的原因是S 有一个比T 严格更大(包含方面)的原子约束集的合取。如果S 具有相同或严格较小的集合,则它是格式良好的。如果两个集合不是按包含排序的,那么这两个模板都不是更专业的,并且没有匹配。

【讨论】:

  • "...那么这是不正确的"It is not.
  • 谢谢。我使模板参数和模板参数无关,现在 GCC 拒绝代码:gcc.godbolt.org/z/d7nT7vhM6。但是 Clang 和 MSVC 仍然接受它,所以我认为它们中存在一些错误。
  • @Barry 你说得对,我忘记了一条规则:如果参数根本不受约束,则忽略参数的约束。我会尽快修复这个例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
相关资源
最近更新 更多