C++ 中用于分离标头/源的模板专业化的稳健方法是什么

2024-02-08

在中等规模甚至大型复杂项目中,将模板声明和定义分开是有用的 以减少编译时间。

然而,在复杂的代码中,程序员的小错误可能会导致不被注意的行为变化, 例如调用通用版本而不是专门化版本。

例子: 由于错过了声明,模板专业化变得不可见。

///////////////////// file  A.hpp /////////////////////

#include <iostream>

template <typename T>

class A 
{
public:
  void foo() 
  {
      std::cerr << " calling generic foo " << std::endl ;
  }
};

// forgetting following declaration leads to an unintended program behaviour
template <> void A< int >::foo();

///////////////////// file  A-foo-int.cpp /////////////////////
#include "A.hpp"

template <> 
void A< int >::foo()
{
  std::cerr << "calling  <int> version of foo" << std::endl;
}

///////////////////// file  main.cpp /////////////////////
#include "A.hpp"

int main(int argc , char** argv)
{
  A<int>* a = new A<int>();
  a->foo();
  return 0;
}

///////////////////// Makefile /////////////////////
CC = g++
CPPFLAGS += -Wall -O3
CXXFLAGS += --std=gnu++0x

all: nonrobust-template-setup

nonrobust-template-setup: main.o A-foo-int.o  
    $(CC)  $(CPPFLAGS) main.o A-foo-int.o  -o nonrobust-template-setup

clean: 
    rm -rf *.o nonrobust-template-setup

//////////////////////////////////////////

问题: 是一种更强大的设置(独立于编译器和平台) 如果,它会是什么样子?

如果没有,测试所需函数版本是否被调用的好方法是什么?


您不能以这种方式分离声明和定义:如果您将专用成员函数的定义放在单独的.cpp文件中,无论您是否在主模板之后立即声明您的专业化,编译器都将无法实例化它,并且链接器将抱怨未解析的引用。

通常,类模板的成员函数的定义位于头文件中,unless你提供一个明确的实例化对于相应的类模板:

template class X<int>; // You should add this to make your program build,
                       // or instantiate the corresponding class template
                       // specialization and invoke the foo() method in the
                       // same translation unit (A.cpp)

一般来说,除非你面临really可怕的编译时间问题,我建议您遵循常见做法,将所有内容放入头文件中,以便由所有需要使用类模板的翻译单元包含:

///////////////////// file  A.hpp /////////////////////

#include <iostream>

template <typename T>

class A 
{
public:
    void foo() 
    {
        std::cerr << "error: called generic foo " << std::endl ;
    }
};

template <> 
void A< int >::foo()
{
    std::cerr << "calling  <int> version of foo" << std::endl;
}

///////////////////// file  main.cpp /////////////////////
#include "A.hpp"

int main(int argc , char** argv)
{
    A<int>* a = new A<int>();
    a->foo();
    return 0;
}   

如果您面临非常可怕的编译时间问题,那么您可以将成员函数定义分开,并将它们放入具有显式实例化的单独翻译单元中,但在 C++11 中,没有干净/简单的方法来确保您的所有专业化分别降级.cpp文件在主模板之后立即声明(正如良好实践所建议的那样)。如果有的话,我想它会很受欢迎,你就不需要来这里询问了,因为大家面临这样的设计问题。

在某些情况下,一些奇特的宏可能会有所帮助,但令人怀疑的是,在真正复杂的项目中,它们会带来比维护痛苦更多的好处。

C++03 标准尝试解决这个问题,引入了export关键字,但是实现经验证明编译器厂商支持太难了,这就是为什么export不再是 C++ 标准的一部分(自 C++11 起)。

希望有更好的解决方案modules将其纳入C++14并提供模板设计的解决方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 中用于分离标头/源的模板专业化的稳健方法是什么 的相关文章

随机推荐

  • 如何使用 jQuery 替换 div 的innerHTML?

    我怎样才能实现以下目标 document all regTitle innerHTML Hello World 使用 jQuery 的地方regTitle is my div id regTitle html Hello World
  • JavaScript 中的 Java byteArray 等效项

    我正在尝试确定哪种编码方案将为 jpeg 文件类型提供数字 1 或 40 文件的起始数字 我正在开发的 REST API 需要一个类似于 1 94 43 34 等 的字节数组 在node js中 我可以将字节数组设置为十六进制或任何其他编码
  • 无法使用 Flask 路由到“/login”?

    当我打字时 login作为url 会出错 例如 from flask import Flask url for render template request app Flask name app route login def index
  • 在 Windows 7 任务栏中显示完整的应用程序?

    在 Windows 7 上 是否可以创建要在任务栏中显示的应用程序 我想到的是一个小部件 例如媒体播放器或天气部件等 像下面的模型一样 任何想法 是的 这是可能的 您正在寻找的是工具栏或有时称为 桌面带 http msdn microsof
  • React Native Navigator renderScene 被多次调用

    我已经被 RN Navigator 难住了一段时间 试图弄清楚为什么 Navigator 渲染推送到其堆栈中的所有路由 最初
  • 如何解决:该应用程序正在从后台线程修改自动布局引擎

    当代码的某些部分从主线程以外的其他线程更改 UI 项目时 此错误会记录到控制台 但我怎样才能找到它在哪里执行此操作呢 此应用程序正在从后台线程修改自动布局引擎 的主要问题是 它似乎在实际问题发生后很长时间才被记录 这可能会使故障排除变得非常
  • react-hook-form:使用 onBlur 模式时验证不起作用

    我正在尝试显示错误yup and react hook form当用户选择超过 5 个复选框但未成功时 相反 当选择第七个复选框时会显示错误 这是简化的代码 imports const schema yup object shape opt
  • 需要有关必须显示 250 000 条折线的 Google 地图应用程序的指导

    我正在为我正在开发的使用 Google 地图的应用程序寻求建议 Summary 用户具有用于搜索满足条件的街道段的条件列表 街道段将用 3 种颜色来表示 分别是低于平均水平 平均水平和高于平均水平 然后 用户单击街道路段 查看一个信息窗口
  • 如何在android中垂直均匀分布按钮/布局?

    我有一个类似于计算器的布局 每行 4 个按钮 大约有 5 行 我使用以下方法创建了每一行LinearLayout 我已经成功地通过使用完全填充了每行的宽度android layout weight 1 在每个按钮中LinearLayout
  • Flexbox:重新排序和堆叠列

    我有三列 我想在特定的屏幕尺寸下交换它们的顺序 当前的顺序是两个 1 4 宽度的列 中间有 1 2 宽度 我想将两个1 4宽度的列变成1 2宽度 并在开始时将它们堆叠起来 我可以使用浮动来复制它 但无法找到使用弹性盒的方法 我正在努力让两个
  • 替换无序列表中的值(html)+ JQuery

    D1 nav d1 span text X1 会改变 span D1 span to span X1 span
  • 通过触摸停止和启动动画。目标C

    我制作了一个在屏幕上移动的动画 我的动画连续循环 如何在点击动画图像时停止动画 然后在松开触摸时让动画继续 我知道如何使用 TouchesMoved 来移动指定的按钮 如下所示 CGPoint point event allTouches
  • virtualenv激活后“python”仍然运行系统版本

    我使用以下命令安装了 Python 2 7 configure prefix usr local enable unicode ucs4 enable shared LDFLAGS Wl rpath usr local lib make m
  • Jupyter Lab 中的 pycwt 包出现 ModuleNotFoundError

    我有一个conda环境 我已经安装了wavelet包pycwt https pypi org project pycwt using conda install n myenv c conda forge pycwt 按照规定蟒蛇云 htt
  • ng2-文件上传访问控制来源问题

    我已经使用这个库进行 angular2 文件上传https github com valor software ng2 file upload https github com valor software ng2 file upload
  • 无法编译调用 tgkill 的程序

    我正在尝试编写一个使用 tgkill 向特定线程发送信号的程序 但是每当我用 gcc 编译它时 我都会收到有关 tgkill 未定义引用的错误 我尝试使用 lpthread 进行编译 但没有帮助 我用谷歌搜索了又搜索 但找不到任何答案 我如
  • .NET Excel 文件解析器

    因此 我工作的公司正在寻找一种方法来验证给定的 xls xlsx 文件是否有效 这意味着检查列 行和其他数据 他让我评估 GrapeCity Spread 和 SpreadsheetGear 但我想知道是否还有其他人可以查看其他外部工具的建
  • 如何解析flutter中的map Json列表?

    I have one Json structure with three maps one is list of products then total and tax I have to parse this json structure
  • 如何知道 npm `unzip` 模块何时完成解压文件?

    我正在使用unzip来自 npm 的模块用于提取 zip 存档的内容 我需要知道何时完成提取并且文件已完全写入磁盘 My code fs createReadStream master zip pipe unzip Extract path
  • C++ 中用于分离标头/源的模板专业化的稳健方法是什么

    在中等规模甚至大型复杂项目中 将模板声明和定义分开是有用的 以减少编译时间 然而 在复杂的代码中 程序员的小错误可能会导致不被注意的行为变化 例如调用通用版本而不是专门化版本 例子 由于错过了声明 模板专业化变得不可见 file A hpp