c++ - 将虚拟方法作为接收迭代器的模板

标签 c++ c++11 templates virtual-functions

我知道不能在 C++ 中为虚方法使用模板(反之亦然),例如讨论 herehere .不幸的是,我不确定在我的案例中如何处理该限制。

我们有一个包含方法模板的类模板:

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/

相关文章:

css - 使 Dojo 或 Ext JS4 小部件的外观和行为类似于 Kendo UI。要求会有多高?

c++ - 可以将 std::numeric_limits<T> 专门用于用户定义的类数类吗?

c++ - 具有可变参数的映射函数并通过字符串调用 c++

c++ - 关于循环中值钳位的优化建议

c++ - error C2679: binary '=': 没有找到接受 'std::basic_string 类型的右手操作数的运算符

c++ - 如何使用内部模板构造模板化函数?

c++ - 如果需要,如何让 std::endl 输出 "\r\n"?

c++ - C++中创建线程的基本问题

c++ - Win32 C++ 可以通过过程发送额外信息

c++ - 函数模板参数推导适用于 gcc,但不适用于 msvc 和 clang