简体   繁体   English

伪造虚拟模板函数C ++

[英]Faking a virtual templated function c++

I realize that virtual template functions are not allowed in c++. 我意识到在c ++中不允许使用虚拟模板函数。 Because of my specific application domain, we deal with sets of algorithms (natural for implementation through polymorphism and inheritance) and need to enforce a common interface. 由于我的应用领域特殊,我们需要处理算法集(通过多态性和继承自然实现),并且需要强制使用一个公共接口。 Particular algorithmic classes work over iterators (not surprising), however we would like to fake virtualization through these templated functions. 特定的算法类在迭代器上工作(不足为奇),但是我们想通过这些模板化函数伪造虚拟化。 Here is an example of a solution we came up with using boost::mpl. 这是我们使用boost :: mpl提出的解决方案的示例。 I realize this is lengthy, but this is a minimal code example that I could create to simulate what I am aiming for. 我意识到这很冗长,但这是我可以创建的最小代码示例,可以用来模拟我的目标。 My specific question follows after the code. 代码之后是我的具体问题。

#include <iostream>
#include <vector>
#include <boost/mpl/list.hpp>
#include <boost/mpl/for_each.hpp>

using namespace std;

class A;
class B;
class C;

typedef boost::mpl::list<B, C> DerivedClassList; 

template<typename Base, typename Iterator>
struct VirtualFunc{
  public:
    VirtualFunc(Base* _memory, Iterator _begin, Iterator _end) : 
      m_memory(_memory), m_begin(_begin), m_end(_end){}

    template<typename T>
      void operator()(T& _t) {
        T* tptr = dynamic_cast<T*>(m_memory);
        if(tptr != NULL){
          tptr->Print(m_begin, m_end);
        }   
      }   

  private:
    Base* m_memory;
    Iterator m_begin, m_end;
};  

class A{
  public:
    A(){}
    virtual ~A(){}

    template<typename Iterator>
      void Print(Iterator _begin, Iterator _end){
        boost::mpl::for_each<DerivedClassList>(VirtualFunc<A, Iterator>(this, _begin, _end));
      }   
};  

class B : public A {
  public:
    B(){}
    virtual ~B(){}

    template<typename Iterator>
      void Print(Iterator _begin, Iterator _end){
        cout << "Begin::" << *_begin << endl;
      }
};

class C : public A {
  public:
    C(){}
    virtual ~C(){}

    template<typename Iterator>
      void Print(Iterator _begin, Iterator _end){
        for(Iterator it = _begin; it!=_end; it++)
          cout << "Iterator::" << *it << endl;
      }
};

int main(){
  vector<size_t> numbers;
  for(size_t i = 0; i<5; i++)
    numbers.push_back(i);

  A* printBegin = new B();
  A* printAll = new C();
  //faking virtualism will print just begin
  printBegin->Print(numbers.begin(), numbers.end());
  //faking virtualism will print all
  printAll->Print(numbers.begin(), numbers.end());
}

So what is the pitfalls of this "fake virtual" templated functions? 那么,这种“伪虚拟”模板函数的陷阱是什么? Is there a better more concise way to do this? 有没有更好,更简洁的方法来做到这一点?

Also excuse the code standards, they are what we use at my workplace. 还请原谅代码标准,它们是我们在工作场所使用的标准。

Why not replace with classic double dispatch pattern. 为什么不替换为经典的双重调度模式。 It seems that you know your class hierarchy at the base level - so I would use the following. 看来您知道基本级别的类层次结构-因此,我将使用以下内容。 It is well known, Visitor or DoubleDispatch pattern and eliminate the non efficient dynamic_cast. 众所周知,Visitor或DoubleDispatch模式并消除了无效的dy​​namic_cast。 Frankly - if I see dynamic_cast<> I always think about double-dispatch, 坦白地说-如果我看到dynamic_cast <>,我总是会考虑两次派遣,

Known clasees: 已知类别:

class A;
class B;
class C;

Start point of virtual-ism: 虚拟主义的起点:

class IVirtualFunc {
  public:
    virtual void callFor(B& memory) = 0;
    virtual void callFor(C& memory) = 0;
};  

Implementation for the template argument: 模板参数的实现:

template<typename Iterator>
class VirtualFunc : public IVirtualFunc {
  public:
    VirtualFunc (Iterator _begin, Iterator _end) : begin(_begin), end(_end) {}
    virtual void callFor(B& memory);
    virtual void callFor(C& memory);
  private:
    Iterator begin;
    Iterator end;   
};

The abstract base class for the actual implementations: 实际实现的抽象基类:

class A{
  public:
    template<typename Iterator>
    void Print(Iterator _begin, Iterator _end) {
        VirtualFunc<Iterator> vFunc(_begin, _end);
        dispatch(vFunc);   
    }
    virtual void dispatch(IVirtualFunc&) = 0;   
};  

First actual implementation with double dispatch for it ( VirtualFunc<Iterator>::callFor(B& b) ): 具有双重调度功能的第一个实际实现( VirtualFunc<Iterator>::callFor(B& b) ):

class B : public A {
  public:
    B(){}
    virtual ~B(){}

    template<typename Iterator>
      void Print(Iterator _begin, Iterator _end){
        cout << "Begin::" << *_begin << endl;
      }
    virtual void dispatch(IVirtualFunc& vf) { vf.callFor(*this); }   
};

template<typename Iterator>
void VirtualFunc<Iterator>::callFor(B& b)
{
     b.Print(begin, end);
}

Second actual implementation with double dispatch for it ( VirtualFunc<Iterator>::callFor(C& c) ): 具有双重调度功能的第二个实际实现( VirtualFunc<Iterator>::callFor(C& c) ):

class C : public A {
  public:
    C(){}
    virtual ~C(){}

    template<typename Iterator>
      void Print(Iterator _begin, Iterator _end){
        for(Iterator it = _begin; it!=_end; it++)
          cout << "Iterator::" << *it << endl;
      }
    virtual void dispatch(IVirtualFunc& vf) { vf.callFor(*this); }   
};
template<typename Iterator>
void VirtualFunc<Iterator>::callFor(C& c)
{
     c.Print(begin, end);
}

And the proof it works: 以及它起作用的证明:

int main(){
  vector<size_t> numbers;
  for(size_t i = 0; i<5; i++)
    numbers.push_back(i);

  A* printBegin = new B();
  A* printAll = new C();
  //faking virtualism will print just begin
  printBegin->Print(numbers.begin(), numbers.end());
  //faking virtualism will print all
  printAll->Print(numbers.begin(), numbers.end());
}

OUTPUT: 输出:

Begin::0
Iterator::0
Iterator::1
Iterator::2
Iterator::3
Iterator::4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM