我知道不能在 C++ 中为虚方法使用模板(反之亦然),例如讨论 here和 here .不幸的是,我不确定在我的案例中如何处理该限制。
我们有一个包含方法模板的类模板:
template <class T>
class BeliefSet : public Belief<T>
{
private:
std::vector<T> m_Facts;
public:
template <class Iter>
void SetFacts(Iter IterBegin, Iter IterEnd, bool Append = false)
{
if(!Append)
{
m_Facts.clear();
}
m_Facts.insert(m_Facts.end(), IterBegin, IterEnd);
}
};
SetFacts()
方法应该能够接收 STL 容器的两个输入迭代器,这就是我们在这里使用方法模板的原因。
现在我想让这个方法 SetFacts()
成为虚拟的,这在 C++ 中是不可能的,目前这段代码的编写方式。那么处理这种情况的典型方法是什么?
最佳答案
基于 CRTP 习语和一些 sfinae 的东西可能可以解决它:
template <class D, class T>
class BeliefSet : public Belief<T>
{
private:
std::vector<T> m_Facts;
template <class Iter>
void SetFactsInternal(char, Iter IterBegin, Iter IterEnd, bool Append = false)
{
if(!Append)
{
m_Facts.clear();
}
m_Facts.insert(m_Facts.end(), IterBegin, IterEnd);
}
template <class Iter, typename U = D>
auto SetFactsInternal(int, Iter IterBegin, Iter IterEnd, bool Append = false)
-> decltype(static_cast<U*>(this)->OverloadedSetFacts(IterBegin, IterEnd, Append), void())
{
static_cast<U*>(this)->OverloadedSetFacts(IterBegin, IterEnd, Append);
}
public:
template <typename... Args>
void SetFacts(Args&&... args)
{
SetFactsInternal(0, std::forward<Args>(args)...);
}
};
您的派生类可以实现OverloadedSetFacts
成员函数来重载 SetFacts
。
此外,您的派生类必须继承自 BeliefSet
,如下所示:
struct Derived: BeliefSet<Derived, MyTType>
{
//...
};
毕竟这是 CRTP 惯用语背后的关键概念。
它遵循一个最小的工作示例(为简单起见在 C++14 中):
#include<iostream>
template <class D>
class Base {
private:
template <class C>
auto internal(char, C) {
std::cout << "internal" << std::endl;
}
template <class C, typename U = D>
auto internal(int, C c)
-> decltype(static_cast<U*>(this)->overloaded(c), void()) {
static_cast<U*>(this)->overloaded(c);
}
public:
template <typename... Args>
auto base(Args&&... args) {
internal(0, std::forward<Args>(args)...);
}
};
struct Overloaded: Base<Overloaded> {
template<typename T>
auto overloaded(T) {
std::cout << "overloaded" << std::endl;
}
};
struct Derived: Base<Derived> {};
int main() {
Overloaded over;
over.base(0);
Derived der;
der.base(0);
}
如您所见,您可以在基类中提供默认实现,并在需要时在派生类中覆盖它。
查看 wandbox .
关于c++ - 将虚拟方法作为接收迭代器的模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41538180/