如何将策略模式与 STL 容器一起使用
How to use the strategy pattern with STL containers?
>假设我有一个名为 BinaryClassifier
的策略接口,它可以接受一个Sample
并返回一个double
,表示Sample
对象属于正类的概率:
struct BinaryClassifier {
virtual ~BinaryClassifier(){}
virtual double classify(std::shared_ptr<Sample> sample) const = 0;
};
我们可能有几种BinaryClassifier
的实现,例如,LogisticRegressionBinaryClassifier
。
Sample
又是一个仅公开两种方法的接口:
struct Sample {
virtual ~Sample() {}
InputFeatures const& get_input_features() const = 0;
double get_label() const = 0;
};
除了这两种方法之外,Sample
的具体实现公开了完全不同的接口(即,它们是不相关的(,它们唯一的共同点是它们可以通过二进制分类器进行分类。
目前为止,一切都好。
当我们决定引入BinaryClassifier::train
方法时,就会出现问题:
struct BinaryClassifier {
virtual ~BinaryClassifier(){}
virtual double classify(std::shared_ptr<Sample> sample) const = 0;
virtual void train(std::vector<std::shared_ptr<Sample>> samples) = 0;
};
此时,以下操作将不起作用:
std::vector<std::shared_ptr<ConcreteSample>> concreteSamples = ...;
concreteBinaryClassifier.train(concreteSamples);
这是因为std::vector<std::shared_ptr<ConcreteSample>>
和std::vector<std::shared_ptr<Sample>>
是两种不相关的类型。
C++的解决方案是依赖模板:
template<class SampleType>
virtual void train(std::vector<std::shared_ptr<SampleType>> samples) = 0; // non-working code, template method cannot be virtual
但是模板方法不能virtual
。尽管如此,我希望BinaryClassifier
成为一个策略界面,因为可能存在许多可能的BinaryClassifier
实现。在这一点上,尽管设计看起来很合理,但我陷入了死胡同。
编辑:此外,在对类型ConcreteSampleB
的对象进行分类时,可能会发生给定的BinaryClassifier
对象使用ConcreteSampleA
向量进行训练的情况
最C++的方式对这种情况进行建模的正确方法?
你可以把你的 BinaryClassifier 变成一个模板类
template<SampleType> class BinaryClassifier
{
virtual void train(std::vector<std::shared_ptr<SampleType>> samples) = 0;
}
您不能在ConcreteSampleA
上训练BinaryClassifier
,然后使用它对任何随机ConcreteSampleB
进行分类。因此,样本类型是BinaryClassifier
固有的一部分。Nullref 的答案在那里是合理的:将示例类型设置为模板参数。
正如您所发现的,这意味着不再需要Sample
接口。好。 std::vector<int>
也不要求int
派生自某些Element
接口。
当你摆脱东西时,InputFeatures
看起来也很可疑。我只想说get_input_features
必须返回一些std::tuple
其成员类型都std::less
定义。由于它不再是虚拟的,因此您不在乎不同的样本类型返回不同的元组。而且我绝对不会硬编码get_label
必须返回double
.无论如何,这是一种奇怪的标签类型。
现在您说使用样本类型 A 进行训练,然后对样本类型 B 进行分类可能是有意义的。这就是你得到改进的地方:似乎实际的兼容性要求是它们返回相同的元组。因此,Nullref 更好的解决方案是在 get_input_sample
返回的元组类型上模板化BinaryClassifier
。
[编辑]此外,classify
不需要共同所有权。传递Sample const&
. train()
真的应该只采用一个迭代器对。C++约定是将一组对象作为范围传递。
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 如何将enable-if与模板参数和参数包一起使用
- 如何将PERF_AMPLE_READ与mmap一起使用
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 在C应用程序中运行C++(带有STL)函数
- 如何将 stl 迭代器与特征一起使用?
- 将 STL 容器与结构一起使用
- 自定义分配器有时会与stl向量一起崩溃
- stl c++优先级队列可以与stl集一起使用吗
- 将"using namespace boost::numeric::ublas;"与 stl 矢量一起使用时出错
- 将我的自定义迭代器与 STL 算法一起使用
- 哪些 STL 算法可以安全地与单通道输入迭代器一起使用
- 将extern模板类与STL类一起使用
- 将STL容器与提升范围适配器一起使用时出现value_type错误
- c++STL算法remove_if与模板一起使用
- STL算法可以与循环列表一起使用吗?
- 为什么scoped_ptr不能与 STL 容器一起使用?
- 是否可以将STL复制功能与地图一起使用
- 如何将策略模式与 STL 容器一起使用