简体   繁体   English

如何最好地实现具有相互依赖类型的模板类

[英]How Best To Implement A Templated Class with Types That Depend On Each Other

As a simplified example, if I have the classes 作为一个简化的例子,如果我有类

template <class T, class U> class ProcessEvent
{
  public:
    ProcessEvent(T* t) : var1(t) { var2 = new U; }
    Process() { var2->Process(var1); }
  private:
    T* var1;
    U* var2;
};

class Foo 
{
  /*data*/
};

class FooProcessor 
{
  void Process(Foo* foo) {/*functionality*/}
};

class Bar
{
  /*data*/
};

class BarProcessor 
{
  void Process(Bar* bar) {/*functionality*/}
};

So the class ProcessEvent can take have two different sets of template types, 所以ProcessEvent类可以有两组不同的模板类型,

ProcessEvent<Foo, FooProcessor>
ProcessEvent<Bar, BarProcessor> 

However, the second template type FooProcessor and BarProcessor are directly implied by the first template type and are implementation details the user doesn't care about. 但是,第二个模板类型FooProcessor和BarProcessor直接由第一个模板类型暗示,并且是用户不关心的实现细节。 My goal is to have the same functionality as above, but have ProcessEvent take only a single template parameter, Foo or Bar. 我的目标是拥有与上面相同的功能,但让ProcessEvent只采用一个模板参数,Foo或Bar。 Other than through specialization of ProcessEvent, can this be done? 除了通过ProcessEvent的专业化,这可以做到吗?

I'm going to assume that you simplified for clarity and are reallyusing smart pointers or at least properly managing the memory. 我将假设你为了清晰而简化,并且真正使用智能指针或者至少正确地管理内存。

The easiest way to do this is with a typedef in the first class: 最简单的方法是在第一个类中使用typedef:

class Foo
{
    typedef FooProcessor Processor;
    // Stuff.
};

Then in your template get rid of U and use typename T::Processor instead. 然后在你的模板中删除U并使用typename T::Processor代替。

You can do this as follows: 你可以这样做:

template<typename T>
class Spec 
{
};

template<>
class Spec<Foo>
{
   typedef FooProcessor type;
};

template<>
class Spec<Bar>
{
   typedef BarProcessor type;
};

Then use Spec<T>::type , with T=Bar or T=Foo, whenever you need BarProcessor and FooProcessor, respectively. 然后在需要BarProcessor和FooProcessor时分别使用Spec<T>::type ,T = Bar或T = Foo。

I would assume that a FooProcessor can only process Foo and a BarProcessor can only process Bar, but the other types could have more than one processor class. 我假设FooProcessor只能处理Foo而BarProcessor只能处理Bar,但其他类型可能有多个处理器类。 Thus you could do it intrusively: 因此你可以侵入性地做到:

class FooProcessor 
{
public:
   typedef Foo value_type;
};

class BarProcessor
{
public:
   typedef Bar value_type;
};

You could use polymorphism: 你可以使用多态:

template< typename T >
class Processor
{
public:
   typedef T value_type;
   virtual ~Processor() {}
   virtual void process( value_type * ) = 0;
};

class FooProcessor : public Processor<Foo>
{
    // implement process
};

You could use an adapter class like Matt Phillips's but in reverse, so it takes the process class as template parameter: 您可以使用像Matt Phillips这样的适配器类,但相反,所以它将进程类作为模板参数:

template<typename T>
class Spec
{        
};

template<> class Spec<FooProcessor>
{           
     typedef Foo type;
};                

template<> class Spec<Bar>        
{           
    typedef BarProcessor type;        
};        

With intrusive typing and the Spec adapter typing your ProcessEvent template would take the processor type as parameter and derive the other one using value_type or type. 通过侵入式键入和Spec适配器键入ProcessEvent模板,将处理器类型作为参数,并使用value_type或type派生另一个。

With polymorphism, your ProcessEvent would take the object type as parameter (Foo or Bar) and would be passed a processor that derives from Processor or Processor to process events. 使用多态性,您的ProcessEvent将把对象类型作为参数(Foo或Bar),并传递一个处理器,该处理器派生自处理器或处理器以处理事件。

If there are huge numbers of events to process and it is always processing them with the same object, the latter method would of course be slightly less efficient as it is processing through a v-table. 如果要处理大量事件并且它总是使用相同的对象处理它们,后一种方法当然会因为通过v表处理而效率稍低。 It depends partly how long they take to process and whether the function that does it could be inlined. 它部分取决于它们处理的时间以及是否可以内联它的功能。

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

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