草庐IT

c++ - 即使有显式实例化,也没有为显式专用模板生成代码

coder 2024-02-11 原文

我从 gcc 4.8.3 和 clang 3.2 得到了一致的行为,但不明白为什么会这样。尽管我有一个类模板的显式实例化,但当我使用模板的完全专用实例时,代码没有生成并且我得到一个 undefined symbol 。

我在文件“temp.hpp”中有一个简单的类模板定义

#pragma once

template <typename T1>
class C 
{
public:
  C (T1 c) : d_c(c) {};
  ~C () = default;

  void print ();
private:
  T1 d_c;
};

请注意,方法“print()”已声明,但未在此处定义。我想要 .cpp 文件中的定义,它将专门用于不同的类型。

所以在 temp.cpp 文件中我有 print() 方法的默认定义

#include "temp.hpp"
#include <iostream>

template<typename T1>
void
C<T1>::print ()
{
  std::cout << "Printing: " << d_c << std::endl;
}

接着是“float”类型的类的特化:

template <>
class C <float>
{
public:
  C (float f) : d_f(f) {};
  ~C () = default;

  void print ()
  {
    std::cout << "float: " << d_f << std::endl;
  }

private:
  float d_f;
};

并且由于定义在 .cpp 文件中,我必须显式实例化我将使用的所有特化。所以我有:

template class C<int>;
template class C<float>;

我的测试驱动程序在 test.cpp 中看起来像这样:

#include "temp.hpp"

int main()
{
  int i = 1;
  C<int> c_int(i);

  float f = 1.2;
  C<float> c_float(f);

  c_int.print();
  c_float.print();
}

编译和链接时出现错误:

test.cpp: undefined reference to `C<float>::print()'

正确生成了 C 的目标代码。我可以使用 nm 看到它:

nm -C temp.o
...
0000000000000000 W C<int>::print()
0000000000000000 W C<int>::C(int)
0000000000000000 W C<int>::C(int)
...

正如我之前提到的,这与 gcc 和 clang 一致,所以我假设这里有一些我不理解的语言规则。

请注意,如果我在文件 temp.cpp 中添加 print() 方法的用法,则会生成代码,但这是愚蠢的,在我的真实代码中是不可能的。对于这个简单的测试用例,它看起来像:

void foo () 
{
  C<float> s(1.3);
  s.print();
}

在激发这个小测试的真实代码中,我的模板有 3 个模板参数,它们组合起来扩展为大约 30 个代码排列。其中一两个我需要一个特化来做一些不同的事情,但其他 28 个我可以不管。

非常感谢任何关于我出错的地方的指示或为什么显式实例化不应该生成代码的语言引用。我每天花 1/2 的时间阅读所有其他关于显式实例化的 stackoverflow 帖子,并相信我正在正确使用它。

最佳答案

来自 [temp.expl.spec]:

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.

我们明确地专注于 C在 temp.cpp 中,但在 test.cpp 中,它在使用前未声明。因此,您的代码格式错误,不需要诊断。您只需移动 C<float> 的声明即可。进入 temp.hpp

始终注意显式特化。该标准非常重视它们:

The placement of explicit specialization declarations for function templates, class templates, [...], can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.

关于c++ - 即使有显式实例化,也没有为显式专用模板生成代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31751138/

有关c++ - 即使有显式实例化,也没有为显式专用模板生成代码的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  5. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  6. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  7. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  8. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  9. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  10. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

随机推荐