我必须在哪里以及为什么必须放置“template”和“typename”关键字?

2024-01-22

在模板中,我必须在哪里以及为什么要放置typename and template关于从属名称?
到底什么是从属名称?

我有以下代码:

template <typename T, typename Tail> // Tail will be a UnionNode too.
struct UnionNode : public Tail {
    // ...
    template<typename U> struct inUnion {
        // Q: where to add typename/template here?
        typedef Tail::inUnion<U> dummy; 
    };
    template< > struct inUnion<T> { };
};
template <typename T> // For the last node Tn.
struct UnionNode<T, void> {
    // ...
    template<typename U> struct inUnion; // intentionally not defined
    template< > struct inUnion<T> { };   // specialization only for T
};

我遇到的问题是typedef Tail::inUnion<U> dummy线。我相当确定inUnion是一个从属名称,VC++ 对此感到窒息是完全正确的。

我也知道我应该能够添加template某处告诉编译器inUnion is a 模板 ID,但具体在哪里呢?那么是否应该假设inUnion是一个类模板,即inUnion<U>命名类型而不是函数?


(See 这里也是我的 C++11 答案 https://stackoverflow.com/a/17579889/4561887)

为了解析 C++ 程序,编译器需要知道某些名称是否是类型。下面的例子表明:

t * f;

这个应该怎么解析呢?对于许多语言,编译器不需要知道名称的含义即可解析并基本上知道一行代码执行什么操作。然而,在 C++ 中,上述内容可能会产生截然不同的解释,具体取决于什么t方法。如果它是类型,那么它将是指针的声明f。但是,如果它不是类型,则它将是乘法。所以 C++ 标准在第 (3/7) 段中说:

有些名称表示类型或模板。一般来说,每当遇到一个名称时,都需要在继续解析包含该名称的程序之前确定该名称是否表示这些实体之一。确定这一点的过程称为名称查找。

编译器如何知道名称是什么t::x指的是,如果t指的是模板类型参数?x可以是可以相乘的 static int 数据成员,也可以同样是可以生成声明的嵌套类或 typedef。如果一个名称具有此属性 - 在知道实际模板参数之前无法查找它 - 那么它被称为附属名称(它“取决于”模板参数)。

您可能建议等待用户实例化模板:

等用户实例化模板后,再去了解其真正含义t::x * f;.

这将有效,并且实际上是标准允许的一种可能的实施方法。这些编译器基本上将模板的文本复制到内部缓冲区中,并且仅当需要实例化时,它们才会解析模板并可能检测定义中的错误。但是,其他实现并没有因为模板作者所犯的错误而困扰模板的用户(可怜的同事!),而是选择尽早检查模板,并在实例化发生之前尽快在定义中给出错误。

因此必须有一种方法告诉编译器某些名称是类型而某些名称不是。

“类型名称”关键字

答案是:We决定编译器应该如何解析它。如果t::x是一个依赖名称,那么我们需要在它前面加上前缀typename告诉编译器以某种方式解析它。标准在 (14.6/2) 中说:

模板声明或定义中使用的且依赖于模板参数的名称是 假设不命名类型,除非适用的名称查找找到类型名称或名称是限定的 通过关键字 typename。

有很多名字typename没有必要,因为编译器可以通过模板定义中的适用名称查找来找出如何解析构造本身 - 例如T *f;, when T是类型模板参数。但对于t::x * f;作为一个声明,它必须写成typename t::x *f;。如果省略关键字并且名称被视为非类型,但当实例化发现它表示类型时,编译器会发出常见的错误消息。有时,错误会在定义时给出:

// t::x is taken as non-type, but as an expression the following misses an
// operator between the two names or a semicolon separating them.
t::x f;

语法允许typename仅在限定名称之前- 因此,人们理所当然地认为,如果不合格的名称这样做的话,那么它们总是会引用类型。

正如介绍性文本所暗示的,表示模板的名称也存在类似的问题。

“模板”关键字

还记得上面最初的引述以及标准如何要求对模板进行特殊处理吗?让我们看下面这个看似无辜的例子:

boost::function< int() > f;

对于人类读者来说,这可能看起来很明显。对于编译器来说并非如此。想象一下以下任意定义boost::function and f:

namespace boost { int function = 0; }
int main() { 
  int f = 0;
  boost::function< int() > f; 
}

这实际上是一个有效的表达!它使用小于运算符进行比较boost::function反对零(int()),然后使用大于运算符来比较结果bool反对f。然而,正如您可能知道的那样,boost::function 在真实生活中 http://www.boost.org/doc/libs/1_54_0/doc/html/function.html是一个模板,因此编译器知道(14.2/3):

名称查找(3.4)发现名称是模板名称后,如果该名称后面跟着

现在我们又回到了同样的问题typename。如果我们在解析代码时还不知道该名称是否是模板怎么办?我们需要插入template紧接在模板名称之前,如指定的14.2/4。这看起来像:

t::template f<int>(); // call a function template

模板名称不仅可以出现在::但也经过了-> or .在类成员访问中。您还需要在那里插入关键字:

this->template f<int>(); // call a function template

依赖关系

对于那些书架上有厚厚的标准语言书籍并且想知道我到底在说什么的人,我将谈谈标准中如何指定这一点。

在模板声明中,某些构造具有不同的含义,具体取决于您用来实例化模板的模板参数:表达式可能具有不同的类型或值,变量可能具有不同的类型,或者函数调用可能最终会调用不同的函数。这种构造通常被认为是depend关于模板参数。

该标准通过构造是否依赖来精确定义规则。它将它们分成逻辑上不同的组:一组捕获类型,另一组捕获表达式。表达式可能取决于它们的值和/或它们的类型。所以我们有,附有典型的例子:

  • 依赖类型(例如:类型模板参数T)
  • 值相关表达式(例如:非类型模板参数N)
  • 类型相关的表达式(例如:转换为类型模板参数(T)0)

大多数规则都是直观的并且是递归构建的:例如,构造为的类型T[N]是一个依赖类型,如果N是一个值相关的表达式或T是依赖类型。详细信息可以阅读部分(14.6.2/1) 对于依赖类型,(14.6.2.2)对于类型相关的表达式和(14.6.2.3)对于值相关的表达式。

从属名称

该标准有点不清楚是什么exactly is a 附属名称。简单阅读一下(你知道,最小惊喜原则),它定义的所有内容都是附属名称是下面函数名称的特殊情况。但既然明确T::x还需要在实例化上下文中查找,它还需要是一个依赖名称(幸运的是,从 C++14 中期开始,委员会已经开始研究如何修复这个令人困惑的定义)。

为了避免这个问题,我对标准文本进行了简单的解释。在表示依赖类型或表达式的所有构造中,其中的一个子集表示名称。因此,这些名称是“从属名称”。名称可以采用不同的形式 - 标准规定:

名称是表示实体或标签(6.6.4, 6.1)

标识符只是一个简单的字符/数字序列,而接下来的两个是operator + and operator type形式。最后的形式是template-name <argument list>。所有这些都是名称,并且按照标准中的常规使用,名称还可以包含限定符,说明名称应该在哪个名称空间或类中查找。

值依赖表达式1 + N不是一个名字,但是N是。所有依赖结构(名称)的子集称为附属名称。然而,函数名称在模板的不同实例化中可能具有不同的含义,但不幸的是,不符合这个一般规则。

依赖函数名称

这不是本文主要关注的问题,但仍然值得一提:函数名称是单独处理的异常。标识符函数名称不依赖于其本身,而是依赖于调用中使用的类型相关参数表达式。在示例中f((T)0), f是一个从属名称。在标准中,这被指定为(14.6.2/1).

附加注释和示例

在足够多的情况下,我们都需要typename and template。您的代码应如下所示

template <typename T, typename Tail>
struct UnionNode : public Tail {
    // ...
    template<typename U> struct inUnion {
        typedef typename Tail::template inUnion<U> dummy;
    };
    // ...
};

关键词template并不总是必须出现在名称的最后部分。它可以出现在用作范围的类名之前的中间,如下例所示

typename t::template iterator<int>::value_type v;

在某些情况下,关键字是被禁止的,详情如下

  • 不允许在依赖基类的名称上写typename。假定给定的名称是类类型名称。对于基类列表和构造函数初始值设定项列表中的名称都是如此:

     template <typename T>
     struct derive_from_Has_type : /* typename */ SomeBase<T>::type 
     { };
    
  • 在 using 声明中,不可能使用template最后一次之后::,以及 C++ 委员会said http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#109不致力于解决方案。

     template <typename T>
     struct derive_from_Has_type : SomeBase<T> {
        using SomeBase<T>::template type; // error
        using typename SomeBase<T>::type; // typename *is* allowed
     };
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我必须在哪里以及为什么必须放置“template”和“typename”关键字? 的相关文章

  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • Ruby 模板:如何将变量传递到内联 ERB 中?

    我有一个内联到 Ruby 代码中的 ERB 模板 require erb DATA a gt HELLO b gt WORLD template ERB new lt lt EOF current key is current value
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐

  • 如何静态断言指针转换是微不足道的?

    假设我有以下类型 struct A int a struct B int b struct C public A public B int c A C 指针可以转换为A 指针根本不调整实际地址 但当C 被投射到B 该值必须改变 我想确保我拥
  • 在 docker 容器内挂载 nfs 共享

    有谁知道如何使用 centos 基础镜像在 docker 容器内挂载 nfs 共享 我试过这个命令 mount server dir mount point 并得到下一个错误 mount nfs rpc statd is not runni
  • 正则表达式:查找没有子串的字符串

    我有一篇大文字 Big piece of text This sentence includes regexp word And this sentence doesn t include that word 我需要找到以 开头的子字符串t
  • 与多个字段和 mongodb 中的 where 条件不同

    我想写一个相当于distinct and where in mongodb SQL查询是select DISTINCT key score from GPC where note test2 and notetwo meet2 id Obj
  • 自定义 iOS Twitter 身份验证页面?

    我正在制作一个移动应用程序 用户可以将他们的 Twitter 帐户连接到该应用程序 我只是有点好奇最好的方法是什么 现在 我希望能够制作自己的自定义页面 无需使用 UIWebView 这可能吗 如果怎样 那么 Thanks 据我了解 您不希
  • 如何在 Node.js server.listen() 中使用可选的主机名参数

    从我到目前为止在教程中读到的内容来看 可选的hostname参数为server listen port hostname backlog callback 一直都是127 0 0 1 环回 0 0 0 0 监听每个可用的网络接口 默认选项
  • Tomcat 中是否可以让一个 appBase 由多个上下文路径提供服务?

    Tomcat 中是否可以让一个 appBase 由多个上下文路径提供服务 我有一个应用程序库 最近替换了第二个应用程序库 我的问题是许多用户仍然访问旧的上下文 我想从单个 appBase 提供现在常见的应用程序 但可以通过任一上下文访问 我
  • Jasmine:可观察到的单元测试 http 服务错误

    我对如何模拟我的 http 服务捕获可观察到的错误感到非常困惑 我已阅读角度文档 但我不明白如何构建测试 我想模拟我的服务中的错误 然后检查它是否捕获了可观察到的错误 我有另一个服务可以创建并抛出可观察到的错误 我的其余服务只是在遇到错误时
  • 我的 MVC 自定义 ControllerFactory 可以工作,但还能更好吗?

    我研究过 Ninject StructureMap 和其他依赖注入和服务定位器框架 但这个问题更多的是关于了解它是如何工作的以及什么可以做得更好 更重要的是 我无意于查看框架的依赖注入源代码 而是了解它在实践 代码中从头到尾是如何实现的 下
  • 如何让 Git 忽略符号链接?

    我的项目文件夹中有符号链接 以便当我在 Windows 10 计算机上的本地开发服务器中运行项目时可以访问大型视频和图像目录 问题是 Git 不允许我执行 add 因为当存在符号链接时 它会给我这个错误 error readlink Pro
  • 您如何向没有 Javascript 之外的编程经验的人解释 Javascript 类型数组?

    最近我经常使用 Canvas 开发一些关于网络游戏的想法 因此 我最近遇到了 Javascript 类型数组 我已经读过一些书 例如MDN https developer mozilla org en US docs Web JavaScr
  • 错误:自构建预编译头以来系统文件已被修改

    我刚刚下载了 xcode 6 的最终版本并编译了一个我正在使用测试版的项目 现在显然生成了以下错误模拟器 有人可以帮助我解决这个问题 fatal error file Applications Xcode app Contents Deve
  • 如何在asp .net core web api中获取后台服务中的主机URL?

    我有一个 Asp Net core Web api 它将运行后台服务来每天安排一些任务并发送一些邮件 在邮件中我需要有 api 的 url 除了控制器之外 还有什么方法可以在后台服务中获取主机 URL 后台服务在 Web 请求的范围之外运行
  • javax.xml.soap.MessageFactory的实例是线程安全的吗?

    有人知道 javax xml soap MessageFactory 的实例是否是线程安全的吗 我找不到任何与之相关的文档 如果您没有看到任何关于某些东西是否是线程安全的文档 您应该假设它不是 如果你假设它是 但事实并非如此 这将避免很多头
  • postgresql 中 mmm yyyy 格式的日期

    我有一个表 其中有一列没有时区的时间戳类型 我想选择该列mmm yyyy格式 例如 2011 年 3 月 怎么格式化成这样呢 我试过 select cast now as date 但它给了我不正确的格式 SELECT TO CHAR NO
  • 用 React 计算 SVG 边界框?

    我正在编写一个使用 React 生成 SVG 的可视化应用程序 我需要的部分之一是标签 即文本 由封闭框包围 带有可变文本 可能会旋转和设置样式 所以我有一个组件NodeLabel 目前具有固定尺寸 render return
  • 使用多列的参数化 IN 子句

    我有一个沿着这些线的查询 我试图通过比较元组来过滤结果集 例如SQL IN 子句中的多列 https stackoverflow com questions 13027708 sql multiple columns in in claus
  • Xcode UI 测试无密码身份验证

    我应该如何测试我的 iPhone 应用程序无密码认证 https medium com ninjudd passwords are obsolete 9ed56d483eb 要注册或登录 Xcode 中的 UI 测试 https devel
  • Solr 到应用程序洞察

    如何配置 Solr 日志以发送到 Azure Application Insights 我看到可以使用 Log4J 附加程序 https learn microsoft com en us azure application insight
  • 我必须在哪里以及为什么必须放置“template”和“typename”关键字?

    在模板中 我必须在哪里以及为什么要放置typename and template关于从属名称 到底什么是从属名称 我有以下代码 template