gpt4 book ai didi

c++ - 伪造一个虚拟模板函数c++

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:59:48 26 4
gpt4 key购买 nike

我意识到 C++ 中不允许使用虚拟模板函数。由于我的特定应用领域,我们处理一组算法(通过多态性和继承自然地实现)并且需要强制执行一个公共(public)接口(interface)。特定的算法类在迭代器上工作(不足为奇),但是我们想通过这些模板函数来伪造虚拟化。这是我们使用 boost::mpl 提出的解决方案示例。我意识到这很冗长,但这是我可以创建的用于模拟我的目标的最小代码示例。我的具体问题在代码之后。

#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());
}

那么这个“伪虚拟”模板函数的陷阱是什么?有没有更好更简洁的方法来做到这一点?

也请原谅代码标准,它们是我们在工作场所使用的。

最佳答案

为什么不替换为经典的双分派(dispatch)模式。您似乎知道基类的类层次结构 - 所以我会使用以下内容。众所周知,Visitor 或 DoubleDispatch 模式消除了非高效的 dynamic_cast。坦率地说 - 如果我看到 dynamic_cast<>,我总是会想到双重调度,

已知案例:

class A;
class B;
class C;

虚拟主义的起点:

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

模板参数的实现:

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;
};

实际实现的抽象基类:

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

第一个双分派(dispatch)的实际实现(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);
}

第二次实际实现双重分派(dispatch) ( 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);
}

它有效的证明:

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());
}

输出:

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

关于c++ - 伪造一个虚拟模板函数c++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10575457/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com