我有一个模板类,我在一个标题中声明一个方法,没有在该标题中定义该方法.在.cc文件中,我定义了该方法的专业化,而不用在头文件中声明它们.在另一个.cc文件中,我调用了存在特殊化的不同模板参数的方法.看起来像这样:

foo.h中:

template<typename T>
class Foo {
public:
  static int bar();
};

foo.cc:

#include "foo.h"

template<>
int Foo<int>::bar() {
  return 1;
}

template<>
int Foo<double>::bar() {
  return 2;
}

main.cc:

#include <iostream>
#include "foo.h"

int main(int argc,char **argv) {
  std::cout << Foo<int>::bar() << std::endl;
  std::cout << Foo<double>::bar() << std::endl;
  return 0;
}

该程序针对所有C标准(c 98,gnu 98,c 11和gnu 11)编译并链接到gcc 4.7.2.输出为:

1
2

这对我来说是有道理的.因为main.cc翻译单元没有看到bar()或它的任何特殊化的定义,所以它期望在某些其他翻译单元中对bar()的调用使用非特异性定义bar()的显式实例化.但是,由于名称变化是可预测的,因此foo.cc中的专业化具有与非特定定义的显式实例化相同的符号名称,因此main.cc能够使用这些专业化,而不会在该翻译单元中声明该特征.

我的问题是这是一个意外,还是C标准规定的这种行为?换句话说,这个代码是否可移植?

我可以找到的最相关的先前的问题是Declaration of template class member specialization,但不包括这种特殊情况.

(如果你想知道为什么这对我很重要,那是因为我使用这样的代码作为一种编译时查找表,如果我不声明专长,则会缩短.)

解决方法

标准(C 11)要求在首次使用之前声明(但不一定定义)明确的专业化:

(14.7.3/6) If a template,a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place,in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a deFinition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function,the
program is ill-formed,no diagnostic required. An implicit instantiation is never generated for an explicit specialization that is declared but not defined. […]

我相信,这实际上只会在您的主要模板定义包含其中一个成员函数的非专门版本的定义时产生影响.因为在这种情况下,当没有声明明确的专业化时,现有的主要定义可能被用来内联编译代码,专业化最终不会被链接使用.

换句话说,如果主模板定义中没有包含成员函数的定义,那么您的链接器技巧可能会被期望在实践中运行,但它不符合标准说明的内容,并且可以让您一旦在主模板中添加内联函数定义,就会发生真正的麻烦.

c – 标题中没有声明的模板类成员专用化的更多相关文章

  1. Smarty模板类内部原理实例分析

    这篇文章主要介绍了Smarty模板类内部原理,结合实例形式模拟Smarty模板类的定义与应用,需要的朋友可以参考下

  2. 带有变量的PHP模板类?

    谢谢.您当前的策略将起作用,并且非常简单.str_replace()是高效和干净的,您可以简单地循环它以用您的变量内容替换精确的标记匹配.但是,缺点是您必须首先将所有模板加载到字符串中,这可能效率很低.另一种非常相似的方法是,您只需使用extract().Extract将采用一组键/值对,并在本地范围内创建变量.如果在同一范围内包含()模板,那么您的变量就可以运行了.像这样的东西:您的模板可能只是普通的PHP.那么你所要做的就是:

  3. 基于轻量级PHP5的模板类/系统

    看一下使用一个新项目的模板系统,它只是一个小型网站,不想使用smarty的开销和“复杂性”.我真的不喜欢模板系统,迫使你使用另一种语言,只是为了让设计师更容易(显然).这样的东西http://www.namepros.com/code/517342-php5-template-class.html是我看的东西,但有些更强大和证明的东西.PHP本身已经是一个模板引擎.那么为什么不削减模板引擎编写的模

  4. 正则的妙用 模板方法创建多类导航

    主要强调正则replace的妙用,之前都没有这样使用过replace上一篇文章链接:http://blog.csdn.net/xiaomogg/article/details/53270321html调用:

  5. 从Angular 2类内部模板调用方法

    我有一个角度2应用程序,有一个名为User的类.此用户有一个名为deleted_at的属性,该属性为null或包含日期时间,显然,如果deleted_at属性不为null,则删除用户.这是我的user.ts文件的外观:User.ts现在我希望我可以用一个简单的行在模板中调用name:然而,这不会返回任何内容,如何在角度2模板中调用某些函数?或者这不允许吗?

  6. C具有变量参数的模板类构造函数

    解决方法这段代码看起来很危险,我认为你的分析为什么它不起作用,编译器没有办法知道在调用时:那些应该通过双打.我会将构造函数更改为:而是让用户将参数作为数组传递.另一种丑陋的解决方案就是这样的:并像这样调用:

  7. c – 基本模板类数据成员在派生模板类中不可见?

    解决方法这是因为useful_是一个非依赖名称,因此在解析模板时查找它,而不是在实例化时查找.非限定名称查找将不会查找,并且从属基类中永远不会查找非相关名称.您可以按如下方式使名称可用依赖,这也将取消非限定名称查找所有这些都可行.或者,您可以使用using声明在派生类中声明名称请注意,在C中没有问题–它只影响B.

  8. c – 从专门的模板类函数调用非专门的模板类函数

    可以从专门的模板类调用非专门的模板类中定义的函数吗?

  9. c – 共享库中模板类和dynamic_cast的显式实例化

    而且,在我想维护一个类结构的前提下,我们要继续使用一个共享库:如何从Base*中成功获取Derived*cast?

  10. c – 标题中没有声明的模板类成员专用化

    ]我相信,这实际上只会在您的主要模板定义包含其中一个成员函数的非专门版本的定义时产生影响.因为在这种情况下,当没有声明明确的专业化时,现有的主要定义可能被用来内联编译代码,专业化最终不会被链接使用.换句话说,如果主模板定义中没有包含成员函数的定义,那么您的链接器技巧可能会被期望在实践中运行,但它不符合标准说明的内容,并且可以让您一旦在主模板中添加内联函数定义,就会发生真正的麻烦.

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&amp;GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部