利用C++模板技术支持多种计算策略

C++模板元编程与表达式模板技术深度解析:从原理到Eigen实战 模板元编程是C++中一种强大的编程技术,其核心范式包含模板特化机制与递归实例化原理。模板特化允许针对特定的模板参数提供专门的实现,这使得代码能够根据不同的类型进行定制化处理。例如,当处理不同数据类型时,可以为某些特殊类型编写特化版本的模板函数或类,以实现更高效或更符合需求的操作。递归实例化则是利用模板在编译时进行递归计算。通过不断实例化模板,直到满足终止条件,从而在编译阶段完成复杂的计算任务。这种方式将计算从运行时转移到编译时,大大提高了程序的运行效率。编译期类型操作是模板元编程的核心价值所在。 阅读详情
任何有经验的程序员和软件设计师都知道,在软件开发中最常见的困境的并不是在问题面前束手无策,而是在一大堆好像都可行的解决策略中选择一个。软件设计就是选择的过程,其困难之处也就在于你得不断地、小心翼翼地做出各种选择。在传统的程序设计模式下,每一次选择都是不可逆转的,你做出了选择,那么随后的开发都将会受到这次选择的剧烈影响。当你发现自己当初的选择错误的时候,可能一切都已经为时太晚。这有点像是走迷宫,而走迷宫时如果你发觉走进了死胡同,还可以掉头换一条路线。但在软件开发中,更换计算策略的成本太高,几乎是无法承受的。如果能够有一种软件设计方法,使更换计算策略的成本大大降低,使你有更多的“悔棋”的机会,那么软件设计的难度就可以大大降低,质量就会得到很大的提高。
另一个常常出现而且令人烦恼的问题是这样的,我们在软件的开发中经常会遇到同类型的问题反复地以不同面貌出现,每次都让你在直觉上感到这几个问题好像差不多。但是当你满怀信心的企图实现一个可重用组件,一劳永逸地解决问题的时候,你就会沮丧地发现,一些细节上的不同使你很难、甚至根本没有办法实现这样一个可重用的组件。于是你不得不一次次地重写类似的代码,使得程序冗长,难于维护。如果我们有一种高度抽象的软件开发技术,把所有细节上的不同都抽象起来,包装在一个统一的接口背后,那么我们就有能力来达成更高程度的代码可重用性,写出适用性更强的软件组件。显然,在这些细节里,类型是一个重要方面,而另一个重要方面就是计算策略。
综合这两点,我们可以看到,把计算策略从一个软件组件中抽象出来将会非常有益。这当然不是一件容易的事情,不光需要在设计上做大量分析,还需要一些特别的编程技术。本文试图用C++提供的模板技术,来给出解决这个问题的一种思路。
1.    一个实际例子
我拿一个手头的例子来说明,在施工进度控制系统里,有一个这样的功能:在已知各种必要信息的情况下,需要估算进行某项工作需要花费的时间。在这里,我的角色不是应用程序的开发者,而是支持组件的开发者。也就是说,我来提供组件,由客户程序员具体使用,完成特定的任务。在这样一个简单的任务里,充满了各种选择,我们把这些选择简述如下:
基本计算模型:可以采用经验估计法,也可以用公式计算法,用户还可能有其他更贴切的计算模型。
精确度要求:通常只有两个选项,一是采用精确计算,二是采用模糊数学理论处理。
环境干扰因素的影响(天气、气候等):可以按照最理想、最糟糕、历年平均和今年预计四种计算策略处理,用户还可能有其他的选项。
其实还可以找出一些策略,但是用来说明问题,上面给出的足够了,单在这里就总共提供了2*2*4 = 16种策略组合。
作为组件开发者,我不可能知道客户程序员在开发应用软件时需要用什么样的策略组合。在形成早期计划时,需要理想估算,可以用公式计算法+精确计算+历年平均策略组合。在施工过程中,经验来得更重要一些,需要用经验估算法+模糊计算+今年预计这个组合形式,施工单位还可能想知道自己最好和最差的情形,也许还会用到预期自然状况为最理想和最糟糕的计算策略。总之,写这个组件的时候我根本不知道应用开发者会怎样使用它,具体的策略组合只有到面对具体问题时才能由应用开发者做出决定,我不能替他们提前做决断,我的任务是必须不折不扣地提供全部的组合可能。
怎么办?将这16种不同方案逐一写来?上面的任何一个策略只要多出一个选择项,组合数目就增加数个,更有甚者,如果突然你发现还需要再多考虑一个因素,比如工作者执行计划的能力因素,那么组合方案会几倍增加。这太可怕了。计算机科学界有一句名言:“永远不要对抗组合爆炸。”所以,我们必须设法重用代码。
现在我把问题归纳如下:
需要设计一种方案来实现一个叫做WorkingTimeEstimater的可重用组件,可以根据使用这个组件的客户程序员的意志自由地组合各种计算策略,并表现出相应的行为。
2.    利用多态性
我们理想的情况是这样的,写一个WorkingTimeEstimater类,在这个类中间有一个成员函数estimate(),用来算出当前工序的耗时,这个类大致的框架看起来像这个样子:
class WorkingTimeEstimate {
public:
     const Time estimate();  //计算当前工序耗时,返回表示时间的Time值
     …
private:
     list<WorkProc>& works_;  //WorkProc代表一个工序,works_
                                   //是准备计算的一系列工序
     list<WorkProc>::iterator current_; //当前工序
     …
};
图1
其中WorkingTimeEstimater::estimate()的伪代码是这样的:
用基本计算模型计算current_工序基准时间t,函数名CalcBasicTime;
按精确度要求修正t,FixAccuracy;
按干扰因素修正t,FixEnvirEffect;
返回t;
estimate()高度一致的算法使我们大有希望实现代码的高度重用。但是,当你深入考虑时,就会发现这是很困难的。记住,我们必须提供各种可能的策略组合,所以绝对不能把具体的选项硬编码在estimate()里。
一个可能的解决方法是建立如下的类关系:

三个抽象基类AbstractAlgo,AbstractAccuracyFixer和AbstractEnvirFixer分别代表抽象的三种计算策略,而在WorkingTimeEstimater中针对每一个抽象类设置一个引用成员变量如下:
class WorkingTimeEstimate {
     …
private:
     AbstractAlgo& basicAlgo_;
     AbstractAccuracyFixer& accuFixer_;
     AbstractEnvirFixer& envirFixer_;
};
const Time WorkingTimeEstimate::estimate() {
     Time t = basicAlgo_.CalcBasicTime(current_);
     t = accuFixer_.FixAccuracy(current_, t);
     t = envirFixer_.FixEnvirEffect(current_, t);
     return t;
}
图3
这样一来客户程序员可以这样构造一个WorkingTimeEstimate对象:
WorkingTimeEstimate wte(/*其他参数*/,
FormulaAlgo(),
AccuracyFixer(),BestEnvirFixer());
这个wte对象初始化时使用了公式计算+精确修正+最佳自然条件的策略组合,如果客户程序员需要别的策略组合,只要在初始化时提供别的策略参数组合。由于CalcBasicTime(), FixAccuracy(), FixEnvirEffect()都是虚函数,wte.estimate()计算中多态性发挥威力,完成客户程序员预期的功能。
我们对这个技术方案做一些分析。首先,代码的重用是基于组合,而不是继承,耦合度低,比较符合OOP的原则。将basicAlgo_, accuFixer_, envirFixer_设为引用型变量,可以强制客户程序员在使用一个WorkingTimeEstimate对象时,必须在初始化时给出具体的计算策略。此外,构造函数WorkingTimeEstimate::WorkingTimeEstimate()可以利用缺省参数机制为客户程序员提供一个缺省的策略组合。如果客户程序员认为有必要增加新的计算策略,他所需要做的只是按照文档说明写一个新的派生类实现自己的计算策略,生成一个对象,然后把这个对象传给WorkingTimeEstimater的构造函数。如果客户程序员感到自己用错了计算策略,很简单,只要更动一行代码就解决问题。
问题到这里似乎解决得很好,但是实际的软件开发中,情形往往并不如此理想,让我们来看一下这种解决方案的几个局限性:
1)    只提供了一种缺省的策略组合。我们是要给客户程序员以充分的选择权,但是也应该化简他们的工作,为他们提供几个最常见的组合,免得每次生成一个新的wte对象都要对着文档看半天。由于C++的缺省参数机制不支持这一点,你只能提供一个缺省策略组合。
2)    一个不容易发现的问题:内存泄漏(memory leak)。我们如果这样调用WorkingTimeEstimater的构造函数:
WorkingTimeEstimate wte(/*其他参数*/,
*new FormulaAlgo(),
*new AccuracyFixer(),
*new BestEnvirFixer());
那么生成的这三个对象在wte.estimate()返回之后就会永远留在heap中的某处。这个问题归根结底是因为我们要利用多态性,就不得不使用polymorphic class,使用虚函数。实际上CalcBasicTime(), FixAccuracy(), FixEnvirEffect()三个成员函数在功能上都与各自对象的this指针没什么关系,如果可能的话最好设为static member function。但是static成员函数不能同时是virtual的,也不可能具有多态性的表现。 唯一的办法是在说明文档里强调不要使用上面的格式初始化wte,然后寄希望于你的老板雇一些比较认真的客户程序员。
3)    假设在所有16种策略组合方案之中,有一类是与众不同的:当出现公式计算法+模糊处理策略组合时,WorkingTimeEstimater::estimate()的算法将发生很大变化,这对我们是很大的问题。只好冒险重载estimate(),通过传递参数的不同来选择不同的estimate()算法。显然,这又要寄希望于高水平的客户程序员。如果他传递了不正确的参数,系统可能会犯下神秘的错误。
4)    最后,一个真正的麻烦。在上面的WorkingTimeEstimate::estimate()的实现中,我们很惬意的写下这样的代码:t = basicAlgo_.CalcBasicTime(current_); 并期望这行代码能够根据basicAlgo_绑定的实际对象表现出多态性。这本身就假定StatAlgo::CalcBasicTime()和FormulaAlgo::CalcBasicTime()具有相同的function signature,都需要一个list<WorkProc>::iterator型参数。但是,如果这个假设不成立,比如StatAlgo::CalcBasicAlgo()声明为:
Time StatAlgo::CalcBasicAlgo(list<WorkProc>::iterator iter,
                                   const StatInfo& si);
那么我们就会遇到很大的麻烦。AbstractAlgo::CalcBasicAlgo()的函数签名应该是什么?怎么写WorkingTimeEstimate::estimate()?即使现在没有出现这个问题,如果以后要向AbstractAlgo类层次里加入新的派生类,也难免遇到问题。我们该怎么设计一个“强壮”的基类?这个问题恐怕困扰过每一个设计过OOP程序的人,从而得了一个专门的名字:fragile base class(脆弱的基类)。
上面的一些问题,是不是让你感到没有希望了呢?其实也不是没希望,仍旧在OOP领域里,仍旧利用polymorphism机制,我们总能够想到一些办法来解决这些问题。比如,我们禁止所有的策略类在heap中建立对象,就可以避免上述的第二个问题(怎么做?参见Meyers96, Item 27)。但是,别忘了本文的题目是“利用C++模板技术支持多种计算策略”,所以我们不能再与polymorphism纠缠不休了。
3.    Policy方案
从现在开始,我们要进入主题了。我们要对付的问题是多策略,而这回我们的武器是C++ template。侯捷先生在他的STL系列文章里提出这样的观点:template与polymorphism一样,都可以实现代码重用,只不过后者是在纵向上(类派生层次)实现,而前者是在横向上实现。既然也能够实现重用性,那么我们就可以把上面基于多态性的多策略方案转而用模板来实现。一旦使用template复用方案,就不再是面向对象程序设计(OOP),而是泛型程序设计(Generic Programming)了。泛型程序设计研究方面公认的专家Andrei Alexanderescu在其最新著作Modern C++ Design中系统地描述了以模板实现的代码复用技术,并且规定了一些新的概念和术语。Policy(直译为“政策”)就是一个关键的概念。一个Policy定义了一个类介面或一个类模板介面(interface),该介面由以下语言结构中的一个或若干个组成:内部定义的类型(包括嵌套的typedef),成员函数和成员变量。凡是提供了符合这个介面定义的类或类模板就成为一个Policy。使用policy的类称为host class。若干个提供相同介面的Policy可以互相替换,从而使相同的host class代码表现不同的功能行为。
我们把上面的例子简化来说明这个概念,只考虑一个基本算法策略AlgoPolicy。我们要求所有的AlgoPolicy类(或模板类)都必须提供一个这样的静态成员函数:static Time CalcBasicTime(list<WorkProc>::iterator)。然后我们编写StatAlgoPolicy如下:
class StatAlgoPolicy {
        typedef list<WorkProc>::iterator LI;
        static Time GetShortestTime(const LI& currwork);
     static Time GetLongestTime(const LI& currwork);
public:
     static Time CalcBasicTime(const LI& currwork) {
         // 下面的具体算法读者不必关心
             Time ts = GetShortestTime(currwork);
          Time tl = GetLongestTime(currwork);
          double tm = (ts + tl) / 2.0;
          return (ts + tl + 4 * tm) / 6.0;
     }
};
图4
上面这个StatAlgoPolicy提供了符合AlgoPolicy介面规定的CalcBasicTime()成员函数,执行估算法计算基本时间,因此是一个符合要求的AlgoPolicy。
有了Policy,我们规定host class如下:
template <class AlgoPolicy>
class WorkingTimeEstimater {
public:
        …
        const Time estimate() {
             Time t = AlgoPolicy::CalcBasicTime(current_);
          //设法修正t
          return t;
     }
private:
     list<WorkProc> works_;
     list<WorkProc>::iterator current_;
};
图5
然后生成一个WorkingTimeEstimater<StatAlgoPolicy>对象:
WorkingTimeEstimater<StatAlgoPolicy> wte;
然后wte.estimate()的行为就是执行估算功能。如果我们再提供一个AccuracyAlgoPolicy,同样遵守AlgoPolicy的介面规范,则如下生成wte对象:
WorkingTimeEstimater<AccuracyAlgoPolicy> wte;
那么wte.estimate()执行的就是精确计算。如果你把不遵守AlgoPolicy介面规范的类作为模板参数传给WorkingTimeEstimater<>,则编译器一定会报错。也就是说,跟OOP一样,编译器会保证你必须遵守规则,无需你自己担心。
照葫芦画瓢,现在我们扩大战线,把所有的三个Policy考虑在内,得到下面的WorkingTimeEstimater定义:
template <class AlgoPolicy,  // 基本算法Policy
class AccuracyPolicy, // 精确性Policy
class EnvirPolicy  // 环境影响Policy
           >
class WorkingTimeEstimater {
public:
        …
        const Time estimate() {
             Time t = AlgoPolicy::CalcBasicTime(current_);
          t = AccuracyPolicy::FixAccuracy(current_, t);
          t = EnvirPolicy::FixEnvirEffect(current_, t);
          return t;
     }
private:
     list<WorkProc> works_;
     list<WorkProc>::iterator current_;
};
图6
我们考虑一下这个技术方案跟前面用多态性实现的方案相比有什么优缺点。首先,他至少与前面的方案有相同的灵活性。其次,由于不是采用虚函数后期绑定,没有运行时开销,也没有vptr和vtable带来的空间开销,所以时空效率都比原方案要好。第三,刚才提到的向客户程序员提供数种缺省的组合方案,在多态型方案里很困难,但是用这里的模板方案就轻而易举:
typedef WorkingTimeEstimater<StatAlgoPolicy, FuzzyPolicy,
PredEnvirPolicy> NormalEstimater;
typedef WorkingTimeEstimater<FormulaAlgoPolicy, AccuratePolicy,
BestEnvirPolicy> IdealEstimater;
就这样短短两条语句,向客户程序员提供了两个缺省组合方案。用户只要用声明语句IdealEstimater iesmtr;就可以获得一个理想WorkingTimeEstimater对象iesmtr。如果想增加更多的缺省组合方案,很简单,只要增加typedef即可。第四,不必担心有什么内存泄漏的问题,这一点不言自明。第五,扩充新的Policy非常方便,不用继承、不用改写虚函数,只要写一个类,符合相应的Policy介面规范,然后作为模板参数传给WorkingTimeEstimater,这样新的Policy就可以在WorkingTimeEstimater<>::estimate()算法中发挥作用。
4.    更进一步
我们在前面的多态性解决方案里提到特殊策略组合带来的特殊算法问题。借助template specialization(模板特殊化)技术,我们可以给出比较妥善的解决办法。所以我们首先要介绍一下模板技术的一些要点和template specialization技术。
模板提供了一个对所有类型都适用的通用方案。例如:
template <class T> void swap(T& a, T& b);
你可以在代码中以两个double或者两个std::complex类型左值(lvalue)作为参数调用swap(),C++编译器会自动地根据上面的那个模板格式为你生成针对具体类型的swap()。由于模板具现化(template instantiation)是一个编译时行为,而且是按需提供,也就是说,你用到了,它才具现化,你没用到,它就会对这些模板代码视而不见(即使有错误也发现不了)。所以这一切就好像是编译器里嵌入了一个很聪明的代码产生机(code generator),可以根据你的模板形式和实际代码自动地为你写代码。C++强大的模板技术和精致的具现化机制使得这个代码产生机非常地聪明和强大。利用这个机制进行程序设计,现在已经发展成为一个专门的方向。可以毫不客气地说,这种方式提供了比OOP更高一层的抽象,因而使程序获得更大的灵活性。
上面的swap()模板,是针对所有类型的通用函数模板,也就是说所有的类型都会采用相同的算法处理,这并不总是一件好事。假设现在你有一种类型ST,这种类型做swap动作时有一种特别高效的算法,那么你可以为这种类型定义一个特殊的swap()版本,与上面通用的swap<T>()形成重载(overload)关系。
void swap(ST& a, ST& b) {…}
根据调用重载函数时的解析规则,编译器在遇到swap()的时候,会根据实际参数寻找最匹配的swap()来调用。这就使得你可以给以ST类型的swap()操作以特殊的礼遇。函数模板借助重载机制达成的这种效果,在类模板里如何实现呢?这就要依赖一个比较新的C++语言特性——模板特殊化(template specializtion,其实也不是新特性,早在1995年就写入C++标准草案第一稿,但是时至今日,还有些主流的编译器如Visual C++不支持此特性)。让我们用实例来说明。
回到我们的时间估计组件。假设在所有16种策略组合方案之中,有一类是与众不同的:当出现公式计算法+模糊处理策略组合时,WorkingTimeEstimater::estimate()的算法将发生很大变化,那么在提供了图6的通用WorkingTimeEstimater定义之外,我们可以利用局部模板特殊化(partial template specialization)定义一个特殊的WorkingTimeEstimater如下:
template <class EnvirPolicy> // 模板参数表中只留下环境影响Policy
// 而在下面的<>中间显式指定两个策略
class WorkingTimeEstimater<FormulaAlgoPolicy, FuzzyFixPolicy> {
public:
        …
        const Time estimate() {
             … // 提供特殊的算法
     }
private:
     list<WorkProc> works_;
     list<WorkProc>::iterator current_;
};
图7
编译器在具现化具体的WorkingTimeEstimater类时,如果发现有FormulaAlgoPolicy和FuzzyFixPolicy的组合,就会自动找到最合适类模板定义,也就是图7的类模板来具现化。因此,你提供的特殊的estimate()就会起作用。这样就可以为公式计算法+模糊处理策略组合的情况提供特殊的estimate()实现。问题得到了解决。
现在回过头去看看在第2节中对于对态性解决方案提出的四个责难,现在已经解决了三个,还剩下一个“脆弱基类”问题还没有解决。实际上这个问题也可以用局部模板特殊化来解决。但是从理论上讲,如果在你使用Policy抽象隔离出可能发生变化的代码段后,estimate()算法还可能因为别的因素而产生变体,那只能说明一点:你的抽象工作进行得不够彻底。按照Andrei Alexandrescu的观点,在Policy-based的设计中,最困难的莫过于发掘出所有的Policies,同时还要尽可能让这些Policies之间保持正交关系,也就是各Policy彼此之间互相独立,互不影响。这叫做正交分解(orthogonal decomposition)。STL的一个伟大贡献就是实现了算法和容器组件之间的正交分解:算法不知道其所作用的容器,容器也不知道哪些算法会作用在其上,两者通过iterator来契合,反而有更大的自由度。这与OOP中把算法与数据结构捆绑封装在一起的思想相比,可谓是别有洞天。而与“程序=数据结构+算法”的传统思想虽然貌似一致,但是在抽象层次上已经不能同日而语了。
5.    推荐阅读
为了说明本文中描述的技术,我根据Andrei Alexandrescu所著Modern C++ Design一书中的代码片断扩充了一个完整的例子程序creator.cpp,实现了创建对象的三种策略(用new,用malloc,用clone),用到了一些比较高级的C++语言特性,如template template parameter,并加上了比较详细的注释,读者有兴趣的话可以看看。请用Borland C++Builder 5.0中的bcc32.exe命令行编译工具这样编译:bcc32 creator.cpp
另外,policy在很多方面与traits技术很相似,而对于traits技术的阐释,以及template partial specialization技术,侯捷先生发表在《程序员》2001年第3、4期上的专栏文章可以说是精彩之至。读者不可错过。另外在侯捷网站上有作者翻译的一篇Alexandrescu发表在C++ Report上的traits文章,也可以作参考。
Alexandrescu的Modern C++ Design第一章在更严格的意义上和更高的层次上描述了policy-based design的思想和方法。有条件的读者一定要读一读这本书。(完)
 
C++泛型编程与模板技术深度解析 泛型编程是现代编程语言中的核心范式,通过类型参数化实现代码复用。C++模板作为编译期多态的实现机制,支持非类型参数、特化、SFINAE等高级特性,在STL容器、算法等领域有广泛应用。工程实践中需注意代码膨胀、编译依赖等问题,C++20引入的概念(Concepts)和约束auto进一步提升了模板编程的安全性和可读性。掌握模板元编程和变参模板等技巧,能够实现类型安全的异构容器等复杂功能,是高性能C++开发的必备技能。 阅读详情

相关推荐

C++模板技术:从泛型编程到模板元编程的深入探索

本文还有配套的精品资源,点击获取 简介:C++模板是一种强大的编程特性,支持泛型代码的编写。它分为函数模板和类模板,允许数据类型在编译时被推断。文章详细介绍了模板技术的多个方面,包括参数推断、特化、偏特化、模板元编程、SFINAE原则、模板别名、模板模板参数以及模板展开。这些技术使得开发者能够创建高效、可复用和类型安全的代码,是C++程序员的重要工具。 1. C+...

weixin_35920379的博客 1166

多策略融合算术优化算法

针对算术优化算法(AOA)在搜索过程中容易陷入局部极值点、收敛速度慢以及求解精度低等缺陷,提出一种多策略集成的算术优化算法(MFAOA)。首先,采用Sobol序列初始化AOA种群,增加初始个体的多样性,为算法全局寻优奠定基础;然后,重构数学优化器加速函数(MOA),权衡全局搜索与局部开发过程的比重;最后,利用混沌精英突变策略,改善算法过于依赖当前最优解的问题,增强算法跳出局部极值的能力。选用12个基准函数和部分CEC2014测试函数进行实验仿真,结果表明MFAOA在求解精度和收敛速度上均有明显的提升。

心升明月的博客 2792

Dev-Cpp5.11:轻量级C++集成开发环境安装包

Dev-Cpp5.11是一个广受欢迎的集成开发环境,为C++开发者提供了一个轻量级、功能完备的代码开发和调试平台。它不仅具备源代码编辑器,还内置了编译器、链接器、调试器和其他工具,使得整个开发流程无需切换多个应用程序。其界面直观且易于上手,使得新手程序员和经验丰富的开发者都能快速投入到项目开发中。Dev-Cpp5.11支持多窗口设计,用户可以根据自己的需求安排界面布局,增加了开发效率。此外,Dev-Cpp5.11还持续更新支持最新版本的C++标准,让开发者能够利用现代C++语言的特性进行高效编程。

weixin_36328210的博客 1117

C++的多策略类

元<类...T>类 多策略{//不用有基类. 元<类 T>空 加一(){T b;压(们,b);} 元<元<类>类 G,整...I>空 动作(序列<I...>){ (G<T>::动作(取<I>(们[I])),...); }// 公: 向量<M>们; 多策略(){(加一<T>(),...);} 元<元<类>类 G>空

个人进步之路 370

f2cpp-开源项目:将Fortran代码转换为C++的Python工具

f2cpp是一个将Fortran 77代码转换为C++代码的工具。它的出现是为了帮助那些仍然在使用Fortran 77进行科学计算的开发者和研究人员。通过这个工具,他们可以将Fortran 77代码转换为C++代码,从而在新的计算环境中运行。开源软件(Open Source Software)是指源代码公开的软件,其开发过程和最终成果都可以被任何人查看、修改和分发。这种模式起源于1998年,以促进软件创新和质量提升为目的。开源社区通常会围绕这些项目形成,社区成员自愿参与项目的开发和维护工作。

weixin_42181686的博客 1922

百度智能云训练图像分割模型+python调用模型并分割图像

目录 训练模型阶段 发布图像分割API 调用图像分割API 创建应用后显示以下两个代码 在pycharm中可以调用API mask解码 依赖库pycocotools安装步骤: 依赖库urllib2的安装 源码下载: 最近上课听老师介绍了一个训练图像分割模型的网站,把数据集上传之后做图像标注,然后进行训练就能得到准确率等指标。 训练模型阶段 图像分割:https://ai.baidu.com/easydl/vision/ 图像分割-->创建模型-->上传数据--&gt

icecreamdinner的博客 1388

【C++深度剖析教程40】使用数值型模板技术计算1+2+3+...+N的值

上一篇文章学习了数值型模板技术,并利用相关技术,实现了C++的数组类模板。点击文章查看上一篇文章:点击链接查看 本篇文章,继续利用模板技术来解决一个问题。 如果想求1+2+3+…+N的结果,有很多种方法。可以循环遍历,可以直接使用公式求解。但是他们都不是最快的方法,我们今天使用模板技术,来最快速的求出结果。 1、回顾 模板参数可以是数值型参数。也就是非类型参数。如下图所示: 我们可以像上面定义一...

厚积薄发 1872

JSBSim开发手册:飞机仿真模型开发指南

JSBSim是一款开源的飞行动力学模型仿真引擎,支持多种飞行器的仿真,包括固定翼飞机、直升机、无人机等。JSBSim的设计目标是提供一个灵活、高效、精确的飞行动力学仿真环境。飞行动力学仿真:实现飞行器的动力学仿真,包括空气动力学、发动机、质量和惯性等模型。控制系统仿真:实现飞行器的控制系统仿真,包括自动驾驶仪、飞控系统等。环境仿真:模拟飞行环境,包括大气模型、风力模型等。本文详细介绍了如何使用C++进行JSBSim开发,包括系统设计、模型实现、代码优化和性能调优等方面的内容。

qq_38334677的博客 4525

C++实现策略模式的2种方法——多态、类模板

方法1:利用多态实现策略模式 #include <iostream> using namespace std; class Strategy { public: virtual void fun() = 0; }; class StrategyA : public Strategy { public: virtual void fun() { ...

SunrayME的专栏 925

TBtools的序列提取步骤

本教程详细介绍了如何使用TBtools软件从原来的FASTA序列中提取特定的DNA序列。

weixin_47509995的博客 1万+

基于 Wi-Fi 的室内定位系统

目前,随着国内外相关从业人员的研究,研究者们提出了众多室内定位技术的理论与方法。在此仅讨论基于 Wi-Fi 的室内定位技术。 WI-FI室内定位 近年来Wi-Fi技术飞速发展,城市中的公共场所如大型超市商场、学校、企业等都已经广泛部署Wi-Fi。Wi-Fi室内定位技术已经出现了很多具有代表性的研究成果,如RADAR系统、Nibble系统、Weyes系统等室内定位系统。2012年,Google把Wi...

温染的笔记 9567

【限时免费】 syscalls-cpp:打造高效系统调用的C++20策略框架

syscalls-cpp:打造高效系统调用的C++20策略框架 项目介绍 syscalls-cpp是一款基于C++20策略模式的创新框架,专为开发高效/安全的系统调用(x86/x64架构)而设计。该项目通过独特的模块化架构,允许开发者在编译时自由组合内存分配策略与存根生成策略,实现对操作系统安全边界的精细控制。其核心突破在于直接解析ntdll.dll的元数据自动获取系统调用号,巧妙优化用户态调用流...

gitblog_01105的博客 466

基于Vector 的AUTOSAR NvM 模块使用

本文主要讲述Vector的两款工具configurator和Developer关于NvM的配置流程,包括如何新建NvM SWC以及添加和修改NvM block,Developer主要涉及NvM SWC的新建、添加新NvM Block以及修改原有的NvM Block;Configurator主要涉及三个模块NvM、Fee以及Fls,以下将分为两个模块对该部分进行介绍。 一、Developer 使用 1.1 新建NvM SWC并实例化 如下图,为Developer左列列表 图 1.1...

Fly_To_Skyhehe的博客 4960

推荐开源项目:CPP C++ Papyrus

推荐开源项目:CPP C++ Papyrus 项目介绍 CPP C++ Papyrus 是一个全面的C++编程资源库,由Caio Rodrigues Soares精心编撰和维护。这个开源项目旨在为开发者提供C++语言的核心概念、标准库、工具以及各种应用领域的实例代码和示例。无论你是初学者还是经验丰富的程序员,都能在这个项目中找到你需要的知识点和实践案例。 项目技术分析 该项目涵盖了C++的各个方面...

gitblog_00003的博客 915

Codex 100个真实案例 - 用AI生成Blender 3D建模脚本(建模师要失业了?)

本案例将展示如何用 Codex 生成 Blender Python API(bpy)脚本,自动创建完整的 3D 模型。我们将从基础几何体开始,逐步实现布尔运算、材质设置、光照配置,最终完成一张精美桌子的 3D 建模——包括桌面、桌腿、倒角、木纹材质。还会实现参数化批量生成不同风格的桌子、渲染输出 PNG 图片、以及 360 度旋转动画。全程用自然语言驱动 Codex,让建模从"点鼠标"变成"说人话"!

yueyeguzhuo的专栏 630

uniapp - 使用 <video> 播放视频黑屏,浏览器控制台报错: DOMException: The element has on supported sources.(详细完美解决方案)

uniapp video 视频播放黑屏,uniapp 报错DOMException: The element has on supported sources.,uniapp如何解决DOMException: The element has on supported sources.,uniapp使用video标签无法播放视频出现黑屏问题处理,uniapp解决video视频黑屏显示0秒,并且浏览器报错DOMException: The element has on supported sources.,un

✅ 精选推荐文章 7055

Light_Glue_CPP:实现高效特征匹配的C++解决方案

Light_Glue_CPP:实现高效特征匹配的C++解决方案 项目介绍 Light_Glue_CPP 是一个基于 C++ 开发的轻量级特征匹配库,它使用了 LibTorch 框架,并针对 CUDA 加速进行了优化。该项目旨在提供一种比传统方法更快、性能更优的特征匹配方案。Light_Glue_CPP 的核心是 LightGlue 算法,该算法在保持卓越性能的同时,大幅提高了运行速度。 项目技术分...

gitblog_00835的博客 978

Agentic RL: 大模型后训练 SFT、PPO和GRPO

本文介绍了从LLM训练到Agentic RL的发展过程。传统LLM训练包括预训练和后训练两个阶段,其中后训练通过监督微调、奖励建模和强化学习等技术优化模型表现。针对智能体在复杂任务中的不足,提出了Agentic RL新范式,将LLM嵌入强化学习框架,通过多步交互、工具使用和环境反馈来优化长期目标。相比传统单轮对话优化(PBRFT),Agentic RL具有状态包含历史上下文、行动类型多样、动态状态转移等特点,更适合解决需要多步推理和规划的任务。这种新方法为开发更强大的智能体系统提供了可能。

Cachel Wood的博客 698

Whisper.cpp:高效语音识别的边缘计算革命

**Whisper.cpp**作为OpenAI Whisper模型的C++移植版本,在保持原始模型强大性能的同时,通过**ggml张量库**实现了在边缘设备上的高效部署。该项目的核心创新在于将原本依赖PyTorch的神经网络模型转换为纯C++实现,大幅降低了运行时依赖和内存占用。 传统的语音识别系统通常需要云端计算资源,而Whisper.cpp通过**量化技术**和**内存优化策略**,使得大型

gitblog_00356的博客 1180

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Cppfront项目解析:探索下一代C++语法Cpp2的实验性编译器

C++作为一门历史悠久的编程语言,其语法复杂性一直是开发者们讨论的焦点。Cppfront项目正是为了解决这一问题而诞生的实验性项目,它提出了"C++语法2"(简称Cpp2)的概念,并提供了首个实现这一语法的编译器cppfront。 ## 项目核心概念 ### 什么是Cpp2? Cpp2是C++的一种替代语法设计,旨在提供: - 更简洁的代码表达方式 - 更强的类型安全性 - 更直观的语义表达...

gitblog_00137的博客 735

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

yaml-cpp量子计算配置解析:C++ YAML库的终极应用指南

yaml-cpp是一个强大的C++ YAML解析器和发射器,专门用于处理YAML 1.2规范配置文件。在量子计算领域,yaml-cpp配置文件解析工具能够高效管理复杂的量子程序参数,为量子算法开发提供完整的配置解决方案。 ## 🚀 为什么量子计算需要yaml-cpp配置管理? 量子计算程序通常涉及大量的参数配置,包括量子比特数量、门操作序列、测量设置等。yaml-cpp作为专业的C++ YA

gitblog_00641的博客 1000

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

如何利用Godot-CPP实现C++高性能游戏开发:专业实战指南

在当今游戏开发领域,性能优化已成为核心挑战。当GDScript或C#无法满足高复杂度计算需求时,Godot-CPP作为Godot引擎的C++绑定库,为开发者提供了原生性能解决方案。本文将深入探索Godot-CPP的技术架构、实现原理及实际应用场景,帮助您掌握这一高性能开发工具。 ## 技术架构解析:Godot-CPP的设计哲学 Godot-CPP的核心设计理念是在保持Godot引擎易用性的同时

gitblog_01096的博客 179

深度解析:stable-diffusion.cpp 在纯C++环境下的高效扩散模型推理架构

stable-diffusion.cpp 是一个基于ggml框架的纯C++扩散模型推理库,专注于为技术开发者提供高性能、轻量级的AI图像生成解决方案。该项目采用与llama.cpp相似的设计思路,支持从SD1.x到SD3.5的多种稳定扩散模型版本,同时兼容FLUX、Wan、Qwen Image等前沿模型,在CPU和GPU后端上均表现出卓越的性能表现。 ## 技术架构解析:ggml框架下的高效推理

gitblog_00361的博客 618
上一篇: 确定一个对象在使用前已经被初始化
下一篇: 怎样在 C++ 中计算对象的实例化次数
undefined_behavior
博客等级 码龄19年 1粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值