使用C ++ 11重复的代码

我目前正在进行一个项目,我有以下问题。

我有一个C ++方法,我想以两种不同的方式工作:

void MyFunction() { foo(); bar(); foobar(); } void MyFunctionWithABonus() { foo(); bar(); doBonusStuff(); foobar(); } 

而且我不想复制我的代码,因为实际的function更长。 问题是我不能在任何情况下调用MyFunction而不是MyFunctionWithABonus来为程序添加执行时间。 这就是为什么我不能只有一个布尔参数,我检查与C + +比较。

我的想法本来是使用C ++模板来虚拟复制我的代码,但我想不出一种做法,我没有额外的执行时间,我不必复制代码。

我不是模板的专家,所以我可能会错过一些东西。

你们有没有想法? 还是在C + + 11是不可能的?

有了模板和lambda,你可以这样做:

 template <typename F> void common(F f) { foo(); bar(); f(); foobar(); } void MyFunction() { common([](){}); } void MyFunctionWithABonus() { common(&doBonusStuff); } 

否则你可以创buildprefixsuffix函数。

 void prefix() { foo(); bar(); } void suffix() { foobar(); } void MyFunction() { prefix(); suffix(); } void MyFunctionWithABonus() { prefix(); doBonusStuff(); suffix(); } 

像这样的事情会很好地做到:

 template<bool bonus = false> void MyFunction() { foo(); bar(); if (bonus) { doBonusStuff(); } foobar(); } 

通过以下方式致电

 MyFunction<true>(); MyFunction<false>(); MyFunction(); // Call myFunction with the false template by default 

“丑”的模板可以通过添加一些漂亮的包装function来避免:

 void MyFunctionAlone() { MyFunction<false>(); } void MyFunctionBonus() { MyFunction<true>(); } 

你可以在那里find一些很好的信息。 这是一个“老”的论文,但技术本身保持完全正确。

假如你可以访问一个很好的C ++ 17编译器,那么你甚至可以推进这个技术,使用constexpr,如果这样的话:

 template <int bonus> auto MyFunction() { foo(); bar(); if constexpr (bonus == 0) { doBonusStuff1(); } else if constexpr (bonus == 1) { doBonusStuff2(); } else if constexpr (bonus == 2) { doBonusStuff3(); } else if constexpr (bonus == 3) { doBonusStuff4(); } // Guarantee that this function will not compile // if a bonus different than 0,1,2,3 is passer else { static_assert(false);}, foorbar(); } 

考虑到OP在debugging方面的一些评论,这里有一个版本调用doBonusStuff()来debugging版本,但不是版本(定义NDEBUG ):

 #if defined(NDEBUG) #define DEBUG(x) #else #define DEBUG(x) x #endif void MyFunctionWithABonus() { foo(); bar(); DEBUG(doBonusStuff()); foobar(); } 

如果你想检查一个条件,你也可以使用assertmacros ,如果它是假的,就会失败(但只适用于debugging版本,发布版本不会执行检查)。

如果doBonusStuff()有副作用,请小心,因为这些副作用将不会出现在发布版本中,并可能使代码中的假设无效。

这里是Jarod42的答案使用可变参数模板略有变化,所以来电者可以提供零或一个奖金function:

 void callBonus() {} template<typename F> void callBonus(F&& f) { f(); } template <typename ...F> void MyFunction(F&&... f) { foo(); bar(); callBonus(std::forward<F>(f)...); foobar(); } 

调用代码:

 MyFunction(); MyFunction(&doBonusStuff); 

另一个版本,只使用模板,没有redirectfunction,因为你说你不想要任何运行时间的开销。 就像我担心的那样,这只会增加编译时间:

 #include <iostream> using namespace std; void foo() { cout << "foo\n"; }; void bar() { cout << "bar\n"; }; void bak() { cout << "bak\n"; }; template <bool = false> void bonus() {}; template <> void bonus<true>() { cout << "Doing bonus\n"; }; template <bool withBonus = false> void MyFunc() { foo(); bar(); bonus<withBonus>(); bak(); } int main(int argc, const char* argv[]) { MyFunc(); cout << "\n"; MyFunc<true>(); } output: foo bar bak foo bar Doing bonus bak 

现在只有一个带有bool参数的MyFunc()版本作为模板参数。

您可以使用标签调度和简单的函数重载:

 struct Tag_EnableBonus {}; struct Tag_DisableBonus {}; void doBonusStuff(Tag_DisableBonus) {} void doBonusStuff(Tag_EnableBonus) { //Do bonus stuff here } template<class Tag> MyFunction(Tag bonus_tag) { foo(); bar(); doBonusStuff(bonus_tag); foobar(); } 

这很容易阅读/理解,可以没有汗水扩大( if条款 – if添加更多的标签,没有样板),当然也不会留下任何运行时间的痕迹。

调用语法相当友好,但当然可以包装成香草调用:

 void MyFunctionAlone() { MyFunction(Tag_DisableBonus{}); } void MyFunctionBonus() { MyFunction(Tag_EnableBonus{}); } 

标签调度是一个广泛使用的通用编程技术, 这里是一个很好的基础知识。