나는'm 현재 프로젝트에서 작업하고 난 다음과 같은 문제입니다.
I have a C++는 방법을 내가 원하는 작업에 두 개의 서로 다른 방법:
void MyFunction()
{
foo();
bar();
foobar();
}
void MyFunctionWithABonus()
{
foo();
bar();
doBonusStuff();
foobar();
}
고 싶지 않을 복제 내 코드이기 때문에 실제 기능은 더 이상. 문제는 나가지 않아야 어떤 상황에서 추가 실행 시간을 프로그램을 때 MyFunction 라고 대신 MyFunctionWithABonus. 그것이 왜 나는 그냥 부 매개 변수는 체크인 C++비교입니다.
내 생각했을 것을 사용하여 C++템플릿을 거의 복제 내 코드,하지만 나는't 의 방법을 생각 하고 있는지't 추가 실행 시간 그리고 난't 이 중복되는 코드입니다.
나는'm 지 전문가와 함께 템플릿 그래서 내가 누락 될 수 있습니다 무언가이다.
어떤 당신의 아이디어가 있습니까? 나는 불가능에서는 C++11?
같은 것을 할 것입니다 잘:
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
"못생긴"템플릿 수 있는 모든 피를 추가하여 몇 가지 좋은 포장지 기능:
void MyFunctionAlone() { MyFunction<false>(); }
void MyFunctionBonus() { MyFunction<true>(); }
을 찾을 수 있습니다 몇 가지 좋은 정보에는 기술있. 즉,"오래 된"지만,기술 그 자체에 머물이 완전히 옳습니다.
제공하는 당신은에 액세스할 수 있는 좋은 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();
}
와 함께 템플릿 및 lambda 한 작업을 수행할 수 있습니다:
template <typename F>
void common(F f)
{
foo();
bar();
f();
foobar();
}
void MyFunction()
{
common([](){});
}
void MyFunctionWithABonus()
{
common(&doBonusStuff);
}
또는 다른을 만들 수 있습접두사
와접미사
기능이 있습니다.
void prefix()
{
foo();
bar();
}
void suffix()
{
foobar();
}
void MyFunction()
{
prefix();
suffix();
}
void MyFunctionWithABonus()
{
prefix();
doBonusStuff();
suffix();
}
주어진 일부 의견의 OP 는 관련 디버깅,여기's 버전을 호출하는doBonusStuff()
디버그 빌드에 대한,하지만 릴리스 구축(정의하는NDEBUG
):
#if defined(NDEBUG)
#define DEBUG(x)
#else
#define DEBUG(x) x
#endif
void MyFunctionWithABonus()
{
foo();
bar();
DEBUG(doBonusStuff());
foobar();
}
사용할 수도 있습니다assert
크로하려면 체크인 상태이고 실패할 경우 false(에 대해서만 디버그 빌드;릴리스 빌드를 수행하지 않습니다 check).
주의 경우doBonusStuff()
가 부작용으로,이러한 부작용이 존재하지 않 릴리스에서 구축하고 있습을 무효로 만들어진 가정 코드입니다.
여기에 약간의 변형에 Jarod42's 을 사용하여 응답 앞 그래서 손님을 제공할 수 있는 하나 이 보너스 기능:
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);
다른 버전만 사용하여 템플릿 및 없 리다이렉션 기능을,이후 말라고 했't 원하는 모든 런타임 오버헤드가 발생합니다. 로 fas 으로 I'm 관심이 증가 컴파일시:
#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
이's 지금의 한 버전이다()
와bool
매개 변수는 템플릿으로 인수입니다.
당신이 사용할 수 있꼬리표를 파견고 간단한 과부하 기능:
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();
}
이것은 쉽게 읽기/해,확장될 수 있습니다 땀이(그리고 보일러하면
절-추가하여 더 많은 태그),그리고 물론을 떠날 것이 없 runtime 합니다.
호출하는 구문에 그것이 매우 친절로 그것입니다,하지만 물론 수 있는 포장으로 바닐라 전화:
void MyFunctionAlone() { MyFunction(Tag_DisableBonus{}); }
void MyFunctionBonus() { MyFunction(Tag_EnableBonus{}); }
태그를 파견이 널리 사용되는 일반적인 프로그래밍 기법,여기](https://arne-mertz.de/2016/10/tag-dispatch/)는 좋은 게시물에 대한 기본입니다.