我已经使用模板来实现路径策略。
#include <fstream>
#include <DefaultPolicy.h>
template<typename PathPolicy = DefaultPolicy>
class FileReader
{
public:
double getNextNumber();
private:
PathPolicy pp;
readNumbers() { std::ifstream myFile(pp.path); }; //And so on
};
我实施了:
[HEADER]
struct DefaultPolicy
{
public:
std::string path
DefaultPolicy()
} ;
[IMPLEMENTATION]
DefaultPolicy::DefaultPolicy() : path("."){}
所以现在我想实施许多不同的政策,如:
[HEADER]
struct UnitTestPolicy
{
public:
std::string path
UnitTestPolicy()
} ;
[IMPLEMENTATION]
UnitTestPolicy::UnitTestPolicy() : path("unittests/resources"){}
[HEADER]
struct OperationalPathPolicy
{
public:
std::string path
OperationalPathPolicy()
} ;
[IMPLEMENTATION]
OperationalPathPolicy::OperationalPathPolicy() : path("/sw/cm/resources"){}
我不确定如何切换我的政策。这些是编译时选择,我可以选择我正在构建的目标,但我唯一的想法是回退到宏来进行选择。如果我这样做,那么我真的不需要政策的模板抽象。
我应该如何在构建时选择策略类?
答案 0 :(得分:4)
但我唯一的想法是回到宏来做出选择
真。
如果我这样做,那么我真的不需要政策的模板抽象。
假。模板抽象可以帮助您最大限度地减少预处理器的使用,并彻底隔离您的策略。
您还可以强制在.cpp
文件中实例化模板类,以避免模板导致的编译时开销,因为您了解所有可能的策略类型。
// filereaderimpl.hpp
namespace detail
{
template<typename PathPolicy>
class FileReaderImpl { /* ... */ };
}
// filereader.hpp
#include <fileheaderimpl.hpp>
#ifdef SOME_BUILD_TIME_CHOICE
using FileReader = detail::FileHeaderImpl<SomePolicy>;
#else
using FileReader = detail::FileHeaderImpl<SomeOtherPolicy>;
#endif
答案 1 :(得分:0)
编辑:我误解了问题,下面的解决方案将允许在运行时选择策略,您要求在构建时选择。
我认为继承可以更好地解决您的问题。
所以你有一个基础PathPolicy
(你可以称它为DefaultPolicy
)类,然后让其他策略继承自PathPolicy
类。
所以你的UnitTestPolicy
变成了
struct UnitTestPolicy : public PathPolicy
{
public:
UnitTestPolicy()
{
path = "blah//blah";
}
} ;
然后在文件阅读器中,仅使用基类来抽象策略类的其他实现。这样你的文件阅读器就不关心政策是什么了;它只是要读取文件。
工作示例here。