您可以用(可能還有其他的)模板參數像這樣增加自己的算法:
enum class algorithm_type
{
type_a,
type_b,
type_c
};
template <algorithm_type AlgorithmType>
void foo(int usual, double args)
{
std::cout << "common code" << std::endl;
if (AlgorithmType == algorithm_type::type_a)
{
std::cout << "doing type a..." << usual << ", " << args << std::endl;
}
else if (AlgorithmType == algorithm_type::type_b)
{
std::cout << "doing type b..." << usual << ", " << args << std::endl;
}
else if (AlgorithmType == algorithm_type::type_c)
{
std::cout << "doing type c..." << usual << ", " << args << std::endl;
}
std::cout << "more common code" << std::endl;
}
現在,你可以通過這個模板參數選擇您的行爲:
foo<algorithm_type::type_a>(11, 0.1605);
foo<algorithm_type::type_b>(11, 0.1605);
foo<algorithm_type::type_c>(11, 0.1605);
的類型,是一個常量表達式產生一個編譯時間決定的分支(也就是說,其他的已知是死代碼並被刪除)。事實上,你的編譯器應該警告你這個問題(你如何處理這個問題取決於你)。
但你仍然可以派遣關運行時值就好:
#include <stdexcept>
void foo_with_runtime_switch(algorithm_type algorithmType,
int usual, double args)
{
switch (algorithmType)
{
case algorithm_type::type_a:
return foo<algorithm_type::type_a>(usual, args);
case algorithm_type::type_b:
return foo<algorithm_type::type_b>(usual, args);
case algorithm_type::type_c:
return foo<algorithm_type::type_c>(usual, args);
default:
throw std::runtime_error("wat");
}
}
foo_with_runtime_switch(algorithm_type::type_a, 11, 0.1605);
foo_with_runtime_switch(algorithm_type::type_b, 11, 0.1605);
foo_with_runtime_switch(algorithm_type::type_c, 11, 0.1605);
算法的內部保持不變(枯枝淘汰,同樣的優化),你是如何到達那裏發生了變化。 (請注意,可以將枚舉的概念進行概括,以便該開關自動生成;如果發現自己的變體極少,則可能很好學習)。
當然,您仍然可以將#define
作爲特定算法默認:
#define FOO_ALGORITHM algorithm_type::type_a
void foo_with_define(int usual, double args)
{
return foo<FOO_ALGORITHM>(usual, args);
}
foo_with_define(11, 0.1605);
所有這些一起給你所有三個優點,沒有重複。
在實踐中,你可以將所有三個重載:重要的是知道在編譯時使用哪種算法的用戶,需要在運行時選擇它的用戶,以及那些只需要默認值的用戶通過項目範圍#define
):
// foo.hpp
enum class algorithm_type
{
type_a,
type_b,
type_c
};
// for those who know which algorithm to use
template <algorithm_type AlgorithmType>
void foo(int usual, double args)
{
std::cout << "common code" << std::endl;
if (AlgorithmType == algorithm_type::type_a)
{
std::cout << "doing type a..." << usual << ", " << args << std::endl;
}
else if (AlgorithmType == algorithm_type::type_b)
{
std::cout << "doing type b..." << usual << ", " << args << std::endl;
}
else if (AlgorithmType == algorithm_type::type_c)
{
std::cout << "doing type c..." << usual << ", " << args << std::endl;
}
std::cout << "more common code" << std::endl;
}
// for those who will know at runtime
void foo(algorithm_type algorithmType, int usual, double args)
{
switch (algorithmType)
{
case algorithm_type::type_a:
return foo<algorithm_type::type_a>(usual, args);
case algorithm_type::type_b:
return foo<algorithm_type::type_b>(usual, args);
case algorithm_type::type_c:
return foo<algorithm_type::type_c>(usual, args);
default:
throw std::runtime_error("wat");
}
}
#ifndef FOO_ALGORITHM
// chosen to be the best default by profiling
#define FOO_ALGORITHM algorithm_type::type_b
#endif
// for those who just want a good default
void foo(int usual, double args)
{
return foo<FOO_ALGORITHM>(usual, args);
}
當然,如果一些實現類型總是比其他一些更糟糕,擺脫它。但是如果你發現有兩個有用的實現,那麼保持這種方式並沒有什麼壞處。
這是我目前正在考慮的事情。 '如果'會在最內層的循環中,所以我擔心性能受到影響。不過,我想優化級別會有所作爲。 – user1149913 2013-03-26 18:46:44