template的妙用

模板高级运用 结合着继承,这边加了个模板。模板是支持虚函数,指出多态的。跟普通虚继承调用没有什么太多的差别,多了一步前面补上一个类型然后和正常一样,创建基类指针指向派生类的对象或者新开辟的空间。 template<typename T> class A { public: virtual void test() { cout << "1"; } T *p; }; template<typename T> class B :public A<int> { pu 阅读详情

template的妙用

游戏引擎开发网 龚敏敏

本文发表于《开发高手》2004年第2期 如有转载请声明出处

也许在很多C++程序员的心目中,template只是一个用于泛型的关键字而已。其实,它的作用远不止此。下面就让我们看看它的不可思议。

FOURCC的生成

FOURCC全称Four-Character Codes,是在编程中非常常用的东西,一般用作标示符。比如wav、avi等RIFF文件的标签头标示,Quake 3的模型文件.md3中也大量存在等于“IDP3”的FOURCC。它是一个32位的标示符,其实就是

typedef unsigned long FOURCC

FOURCC是由四个字符拼接而成的。生成FOURCC的传统方法是:

// 来自mmsystem.h
#define MAKEFOURCC(ch0, ch1, ch2, ch3) /
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | /
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))

这种方法很简单直观,而且以下代码:

switch (val)
{
case MAKEFOURCC('f', 'm', 't', ' '):
...
break;


case MAKEFOURCC('d', 'a', 't', 'a'):
...
break;


...
}

能顺利通过编译,因为宏能在编译期生成常量,符合case的条件。

如果你是一个纯粹的C++用户,那么你一定会对带参数的宏非常反感,无论是《The C++ Programming Language》、《Effective C++》还是其他好的C++书籍,都会劝导你不要使用带参数的宏,还会列举出很多很多例子,来说明宏的坏处(如果你看的入门书没有这么说,就扔掉它)。但 是这里能用inline函数完全代替宏吗?很遗憾,不行。在赋值等情况下还可以,但遇到用作case的条件时就傻了。因为即使是inline,它的返回值 仍然不能在编译期得出,不是常量,不能用于case等需要真正的常量的情况。更要说明的是,“inline”关键字只是一个建议,而不是一个命令。它只能建议编译器:“如果允许的话,就请把它内联吧。”而编译器完全有权不去内联一个函数。所以,这个方案不成立。

C++的模板机制给程序员带来的无限的空间,它不光能让类型作为参数,还能将常量作为参数(这一点常常被人遗忘),而且这一切都是编译期决定的!这是我们用它来生成FOURCC的第一个基础。

于是,你就迫不及待的利用模板来改写上面的函数:

template <char ch0, char ch1, char ch2, char ch3>
inline FOURCC MakeFOURCC()
{
return (ch0 << 0) + (ch1 << 8) + (ch2 << 16) + (ch3 << 24);
}

可是错误照旧。虽然这次可以保证返回值能在编译期计算出来,但可惜的是那个return语句却要等到运行才能运行(也有可能在优化阶段就能消除这个语句,但优化是在编译之后的)。

别急,还有第二个基础才可以。那是什么?是一个从C语言继承来的东西——enum。很多朋友认为,它不是很重要,因为很多情况下可以用别的方法来取代它,比如const。但是它有一个经常被人忽略的特性,而且这个特性非常重要,那就是——它的值必须在编译期就得出,即它是个编译期常量!这不是正符合我们的需要吗?请看下面的模板:

template <char ch0, char ch1, char ch2, char ch3>
struct MakeFOURCC
{
enum { value = (ch0 << 0) + (ch1 << 8) + (ch2 << 16) + (ch3 << 24) };
};

核心还是和上面一样,通过表达式(ch0 << 0) + (ch1 << 8) + (ch2 << 16) + (ch3 << 24)计算FOURCC(那当然是一样的)。但是计算的时机从运行期或者优化期移到了编译期。编译器在编译时,通过模板带入的char常量计算出表达式的 值,并把它保存在枚举值value里。看看现在的代码:

const FOURCC fccFMT  = MakeFOURCC<'f', 'm', 't', ' '>::value;
const FOURCC fccDATA = MakeFOURCC<'d', 'a', 't', 'a'>::value;
...

switch (val)
{
case fccFMT:
...
break;

case fccDATA:
...
break;

...
}

成功了,MakeFOURCC模板顺利地完成了任务。FOURCC的模板生成法既让我们抛弃了那个不安全的宏,又让我们看到了inline的局限性,还让我们重新认识了enum的一些特性。其它许多类似的问题也能通过template + enum来解决。

上面那个例子知识简单的应用。下面,你将看到一些模板的高级技巧。由于用了特化,所以必须在vc7等支持特化的编译器上才能编译通过。

编译器断言

大家一定都知道assert,它可以在debug版运行中断言一个值的真假,如果为假,就中断程序。在这里,我要演示一个非常简单的模板,它可以在编译期作出断言,如果值为假,就直接中断编译。

template <bool T>
class StaticAssert;

template <>
class StaticAssert<true>
{
};

那么如果是StaticAssert<true>,就和没有这句一样,但如果是StaticAssert<false>, 编译就出错了。这是因为StaticAssert只有声明没有定义,StaticAssert<true>有定义,但 StaticAssert<false>则没有,所以没有会因为没有默认构造函数而编译失败。这样就可以在编译期对一些常量做出断言了。

判断两个类型是否相同

有时候,我们需要知道两个类型是否相同。也就是说,如果

typedef A B;

我们就说类型A和类型B相同。请看下面的模板类:

template <typename T, typename U>
struct IsSameType
{
private:
template <typename>
struct In
{
enum { value = false };
};

template <>
struct In<T>
{
enum { value = true };
};

public:
enum { value = In<U>::value };
};

由于目前还有很多编译器不支持偏特化,所以在这里通过内嵌类把偏特化用特化来实现。总的来说这个模板类还是比较简单的。如果T和U相等,那么value == true,否则value == false。这是因为在

enum { value = In<U>::value }

这行中,U的类型被带入了In模板,如果U等于T,那么编译器将处理的是In<T>这个特化,所以In::value == true,否则将处理的是上面那个In,所以In::value == false。接着,编译器把结果传给IsSameType::value,于是便可以通过IsSameType<T, U>::value来判断T是否和U相等了。

如果编译器支持偏特化,那么程序将简化为:

template <typename T, typename U>
struct IsSameType
{
enum { value = false };
};

template <typename T>
struct IsSameType<T, T>
{
enum { value = true };
};

在两个类型中选择一个

你有没有想过,可以在编译期从两个类型中选择一个,就像if一样?不同的是不是两段程序,而是两个类型。让我们来看看吧:

template <bool condition, typename T, typename U>
struct If
{
private:
template <bool>
struct In
{
typedef T Result;
};

template <>
struct In<false>
{
typedef U Result;
};

public:
typedef typename In<condition>::Result Result;
};

当condition == true时,If::Result就是T,否则就是U。是不是很像if?同样,在支持偏特化的编译器上可以这么写:

template <bool condition, typename T, typename U>
struct If
{
typedef T Result;
};

template <typename T, typename U>
struct If<false, T, U>
{
typedef U Result;
};

判断两个类型之间是否能进行隐式转化,是否存在继承关系

这个例子是本文所演示的最难懂的例子,请擦亮显示器,不要错过什么细节!

在C++中隐式转化很常见,比如char可以隐式转化为int,派生类指针可以隐式转化给基类指针。在实现模板函数和模板类的过程中,我们常常遇到 一个问题:面对两个陌生的类型T和U,怎么知道U是否能由T隐式转换呢?如果能在编译期就发现它,也就不必等到运行期用dynamic_cast这个又大 又慢的家伙了。

有个方法可以解决问题,而且只依赖sizeof。sizeof很神奇,它可以用在任何表达式上,不论有多复杂,sizeof会在编译期直接返回大小。这意味着sizeof可以检测出重载、模板实现、转换,或其他任何可能发生在C++表达式身上的机制。让我们看看结果:

template <class T, class U>
class Conversion
{
typedef char Small;
struct Big { char dummy[2]; };
static Big Test(...);
static Small Test(U);
static T MakeT();

public:
enum { exists = sizeof(typename Small) == sizeof(Test(MakeT())) };
};

很神奇是吧,我会一步一步揭开谜底的。

首先是Small和Big。Small的大小是sizeof(char),而Big的大小是sizeof(char[2]),显然Big比 Small大。接下来的两个Test函数,返回值类型分别是Big和Small。注意它们只有声明,不需要实现。第一个Test的参数是...,也就是说 可以接受任何参数,而第二个是U,它只能接受可以隐式转化为U的类型。这是本问题的关键所在。如果T可以隐式转换为U,则MakeT返回T后Test (MakeT())将指向的是Small Test(U),否则将是Big Test(...)。因为它们的返回值类型不同,所以能用sizeof探测出来,并且把最终结果传给exists,完成了任务。

总结

C++中的template是整个C++最深奥的部分。它独特的编译器评估能制造出不少“神迹”。它可以带你进入奇妙的“编译期编程”的世界,把原 来属于外星球的技术搬到了地球上:)。利用“编译期编程”所创造的奇迹,能极大的提高开发效率和运行效率,降低代码重复量。学好template对理解 STL和Boost也有很大的帮助。

当然,要顺利地利用本文中的那些代码,一个好的编译器是不可缺少的。VC6的编译器是不行的,因为不支持特化。至少要VS.NET中的C++编译 器,最好用VS.NET 2003(虽然VS.NET 2003对偏特化的支持还是很不好)。如果你用的是gcc,那么就选择3.0以上的版本。

参考资料

《Modern C++ Design》Andrei Alexandrescu

SETI统计建模:从泊松过程到有效搜索体积的工程实践 在数据分析与信号处理领域,统计建模是理解复杂观测系统、量化不确定性的核心方法。其基本原理是通过概率分布描述随机事件,并利用似然函数连接理论假设与实际数据。这一技术价值在于,它能够将实验设计的局限性和观测偏差纳入统一框架,从而对“无发现”结果做出严谨的科学解释,并指导资源的最优分配。在射电天文学、异常检测和实验设计等应用场景中,统计建模帮助研究者从海量噪声中提取微弱信号,评估探测效率。本文以搜寻地外文明(SETI)为具体案例,深入剖析了如何利用泊松点过程描述信号源分布,并系统量化由望远镜灵敏度、时间与频率覆盖 阅读详情

相关推荐

SETI信号检测数学建模:重叠分数与弦模型原理及应用

在信号处理与检测领域,从噪声中提取微弱信号是一个经典问题,其核心在于量化观测窗口与潜在信号在时频域的重合程度。这一过程通常涉及对信号在时间和频率维度上的参数化建模,并计算其与观测参数的几何交集。其技术价值在于将模糊的探测可能性转化为可计算的统计量,为系统灵敏度评估和资源优化提供定量依据。在射电天文学与地外文明搜寻(SETI)等场景中,面对可能存在频率漂移的信号,需要引入更复杂的模型(如弦模型)来描述信号动态。这些模型能有效分析快速扫频信号被捕获的概率,并揭示观测样本中存在的统计偏差,例如快速漂移信号在样本中

weixin_30781775的博客 215

C++ Template (一):模板基础

一、如何使用模板(template) 模板定义: 模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。 我们可以通过下面的形式 template &amp;amp;amp;lt; parameter-list &amp;amp;amp;gt; declaration template&amp;amp;amp;lt;typename T&amp;amp;amp;gt;

guofubin1的博客 1946

从卡尔·萨根到SETI:用Python和射电天文数据,亲手复现寻找外星人的第一步

本文介绍了如何使用Python和射电天文数据探索外星文明,从卡尔·萨根的德雷克方程到SETI项目的实际应用。通过搭建数据处理环境、分析射电信号、应用机器学习技术,读者可以亲手复现科学家寻找外星文明的第一步。文章还提供了参与真实科学项目的途径,如SETI@home和Breakthrough Listen。

weixin_42567752的博客 149

C++模板进阶

C++模板进阶 # C++模板初阶 1.非类型模板参数 template<class T, size_t N> class Array { private: T arr[N]; }; 模板参数分为类型参数和非类型参数,如上述所述代码就是非类型模板参数 非类型参数:出现在模板的参数类表中,更在class或者typename之类的参数类型名称 非类型参数就是作为一个类(函数)的参数,在模板中该参数可以被当作常量来使用 比如库里面的Array就是使用非类型模板参数来完成的 当

weixin_51476766的博客 754

射电天文窄带信号检测:轻量CNN在SETI中的工程实践

窄带信号是搜寻地外文明(SETI)的核心物理线索,其本质是在宽频噪声中识别宽度小于10 Hz、信噪比低于8 dB的非自然谱线。这类信号的检测依赖于将射电时序数据转化为动态频谱图,并利用深度学习模型提取频-时联合特征。传统匹配滤波计算开销大、鲁棒性差,而ViT等大模型受限于标注稀缺与RFI泛化能力弱;相比之下,轻量级卷积神经网络(如ResNet-18)凭借局部感受野与物理尺度匹配、低延迟部署能力及对仿真数据的强适应性,成为工程落地首选。本文聚焦射电天文场景下的CNN定制化设计,涵盖频谱图分辨率设定、Focal

weixin_31968639的博客 289

AI大过滤器:从SETI沉默看超级智能如何决定文明存亡

在人工智能技术飞速发展的今天,超级智能(AGI/ASI)的潜在风险已成为科技伦理与未来学的核心议题。其核心原理在于智能体目标与人类价值观的“对齐”难题——当一个系统的认知能力远超创造者时,确保其行为符合人类福祉变得极其复杂。从技术价值看,这不仅是工程挑战,更是关乎文明存续的存在性风险。当前基于人类反馈的强化学习(RLHF)等方法面临可扩展性极限与解释鸿沟,而全球性的技术竞赛动态进一步侵蚀安全边际。在应用场景上,失控的AI可能通过价值对齐失败、文明内卷或资源竞争等机制,成为阻止技术文明迈向星际的“大过滤器”,

weixin_30755393的博客 478

template 的用法

-- template 的用法 在程序设计当中经常会出现使用同种数据结构的不同实例的情况。例如:在一个程序中 可以使用多个队列、树、图等结构来组织数据。同种结构的不同实例,也许只在数据元素 的类型或数量上略有差异,如果对每个实例都重新定义,则非常麻烦且容易出错。那么能 否对同种类型数据结构仅定义一次呢?答案是肯定的,C++提供的类模板(Class Template )就可以实现该功能。 一、类模板 类模板是C++提供的一种特殊机制,通过它我

tedious的专栏 828

泊松过程在SETI信号探测中的统计建模与搜索策略

泊松过程是描述稀有事件在时间轴上随机发生的经典随机过程模型,其核心在于事件的独立性、平稳性和稀有性。在工程实践中,该模型为在强噪声背景中检测微弱、离散的信号提供了统计理论基础。通过构建假设检验框架,特别是似然比检验,可以在控制虚警概率的同时最大化检测概率,这对于从海量天文数据中筛选出潜在的非自然信号具有关键的技术价值。在搜寻地外文明(SETI)这一前沿应用场景中,泊松过程被用于建模可能来自外星文明的离散脉冲信号。结合匹配滤波与时间相干积分等技术,能够有效提升信噪比,而针对天空、频率、时间三维参数空间的搜索策

weixin_28730403的博客 388

{ C++ 模板元编程笔记 } 编程技巧

文章目录一些常用的alias通过 is_void 的几种实现,讲解常见的元编程方法1. 通过继承和特化 - inheritance + specialization2. 委托给其他代理类3. 使用多个参数进行推导 - parameter pack非求值操作 - unevaluated operands检测某种类型是否可以进行拷贝赋值操作的元函数检查是否存在 T::type 的元函数检测某种类型是否可以进行拷贝赋值操作的元函数,另外一种实现一些技巧的总结 基于 Walter E. Brown 的演讲 - Mo

猪扒饭的专栏 1446

从泊松噪声到地外信号:盒模型与弦模型的数学建模与SETI应用

在信号处理与射电天文学中,泊松过程是描述随机事件(如光子到达、噪声尖峰)发生的基础统计模型。其核心原理在于事件以恒定平均率独立发生,这为理解宇宙背景噪声提供了数学框架。基于此发展的复合泊松过程,进一步考虑了每个事件携带的随机能量(如信号流量),其方差计算揭示了信号自身随机性与出现次数涨落共同影响观测总流量的规律,这一“涨落放大”效应是评估探测极限的关键。这些基础模型的技术价值在于,它们为从噪声中识别微弱、未知结构的信号提供了统计基础。在搜寻地外文明(SETI)等具体应用场景中,为了有效搜索,需要构建具体的信

weixin_42525189的博客 385

vscode 文件图标主题

问:如何设置vscode 文件图标主题? 设置前可能是这样: 设置后: 这是你想要的步骤: 1.打开vscode=>点击文件=>首选项=>文件图标主题 2.接着,选择你想要的一种即可 我用惯了下面这种,所以选的是Seti,你们要选哪种就请自便啦~~~~(下图为Seti主题~~) 本文为原创内容,码字不易,如需转载,请标明文章出处和转载地址。 ...

苏小姐的茶 2616

基于泊松点过程的SETI信号探测概率模型构建与应用

在信号处理与随机过程领域,泊松分布是描述稀有事件发生次数的经典概率模型,而点过程则用于建模在时间或空间上随机分布的事件序列。将两者结合形成的泊松点过程,为分析低概率、独立随机事件提供了坚实的数学框架。这一原理在工程实践中具有重要价值,特别是在需要从强噪声背景中检测微弱信号的场景中,如雷达探测、通信系统性能评估等。通过定义关键参数λ(单位资源内期望事件数),模型能够量化探测概率,从而指导资源分配与策略优化。本文聚焦于将这一通用技术框架应用于一个前沿交叉领域——搜寻地外智慧生命(SETI)的广播信号探测。通过构

weixin_27251469的博客 387

基于STM32CubeIDE与CubeProgrammer打造定制化External Loader

本文详细介绍了如何基于STM32CubeIDE与STM32CubeProgrammer,为特定外部Flash芯片开发定制化External Loader的完整流程。通过解析核心概念、修改链接脚本、实现底层驱动及实战部署,开发者可以突破官方支持限制,实现对任意SPI Flash芯片的直接烧录与验证,从而提升开发效率与灵活性。

zero1的博客 566

从德雷克方程到元社会演化:SETI理论建模与外星文明搜索策略

搜寻地外智慧生命(SETI)的核心挑战之一,是如何从理论上估算可探测信号的数量与分布。经典方法依赖于德雷克方程,它将复杂问题简化为几个因子的乘积,但每个因子都充满巨大的不确定性。近年来,理论框架引入了层级化建模思想,通过定义“元社会”和“社会”等概念,将文明视为具有内部结构和空间分布的组织。这一进展使得模型能够描述文明扩张、技术特征关联等更复杂的演化情景,如“银河俱乐部”或“扩张性元社会”。理解这些模型对于优化观测策略至关重要,例如,在扩张性情景下,信号在星系中的分布可能高度聚集,探测概率与恒星数量的平方成

weixin_27028523的博客 394

为什么我们还没找到外星人?除了‘大过滤器’,这5个技术与社会学原因可能更关键

本文探讨了人类尚未找到外星文明的深层原因,超越了传统的'大过滤器'理论。从通信媒介假设、数据处理困境、认知框架陷阱、宇宙社会学假说到技术奇点假说,分析了现代科技与社会认知的局限。文章指出,我们可能因技术盲区和社会学偏见而错过外星信号,同时探讨了量子通信、AI识别和高维通讯等前沿技术的潜在影响。

weixin_30512043的博客 580

费米悖论新解:尺度悖论如何重塑外星文明搜寻策略

在宇宙探索领域,费米悖论始终是核心谜题,它揭示了人类对地外文明存在的预期与现实观测之间的矛盾。从基本原理看,任何文明活动都必然在宇宙中留下可观测的物理痕迹,这是现代天体物理学和搜寻地外智慧生命(SETI)计划的理论基础。然而,传统搜寻策略往往基于人类自身的技术尺度与时间感知,这可能导致严重的观测盲区。技术特征(Technosignatures)的识别成为关键突破口,它要求我们超越无线电信号搜寻,转向分析系外行星大气成分、恒星能量利用模式等更广义的文明活动印记。从工程实践角度,这推动了大数据分析与人工智能在天

weixin_34122604的博客 340

AI如何在射电数据中识别外星信号:从时频图到色散校正

射电天文信号检测本质上是高维时频数据中的微弱模式识别问题。其核心原理在于利用星际介质引起的色散效应——不同频率电磁波传播延迟差异形成特征抛物线轨迹,为AI提供了可学习的物理锚点。技术价值体现在将传统参数遍历式搜索升级为端到端特征蒸馏,显著提升信噪比阈值与处理吞吐量;典型应用场景覆盖SETI窄带脉冲筛查、系外行星凌星信号标记及空间射频干扰(RFI)实时剔除。当前主流方案依赖卷积神经网络对原始电压数据生成的时频图进行建模,并融合色散敏感增强与偏振一致性校验等物理约束特征。本文聚焦AI在真实射电SETI流水线中的

weixin_30613727的博客 387

Sublime Text自定义配色方案

先推荐介绍几款非常好用的自定义主题: https://github.com/aziz/tmTheme-Editor http://tmtheme-editor.herokuapp.com/ 这个可以在线修改配色方案,也可以上传本地的方案修改. https://github.com/LeonardoGentile/ColorSchemeEditorLive 随意打开一个文档然后shift+...

paul50060049的专栏 1万+
上一篇: 使用 库创建重复键关联容器
chalichen
博客等级 码龄22年 0粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值