您可以用(可能还有其他的)模板参数像这样增加自己的算法:
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