Defining Attachment Patterns in C ++

I am overusing C ++ templates a bit and I am having a hard time figuring things out. Let's say I have two types that really need to inherit from the base type, but for speed reasons I can't afford the overhead of a virtual function (I've been comparing this and virtual calls are ruining things for me!).

Firstly, here are the two classes I have

template<class DataType> class Class1
{
    //Lots of stuff here
}

template<Class DataType> class Class2
{
    //The same stuff as in Class1, but implemented differently
}

      

In typical design oo Class1

and Class2

inherit from IInterface

and I could have a function that looks like

DoStuff(IInterface& MyInterface)
{
}

      

But I can't do it, so I did it

template <class C>
DoStuff(C& c)
{
}

      

I know this is not very pretty since there is nothing (at the compiler level) to ensure that Class1

both Class2

implement the same interface, but for speed reasons I am breaking some rules.

I'd love to create a callback function on DoStuff

, but I can't figure out how to make it work with templates (especially since it's hidden there.

For example, this is working right now

DoStuff(char* filename)
{
    switch (//figure out the type i need to make)
    {
    case 1: return DoStuff(Class1<int>(filename));
    case 2: return DoStuff(Class1<double>(filename));
    }
}

template<class DataType>
DoStuff(DataType* pdata)
{
    return DoStuff(Class2<DataType>(pdata));
}

template<class C>
DoStuff(C c)
{
  c.Print();
}

      

Now I know what you are asking, why use Class1

u Class2

? Well, the main difference between working with a file and working with memory is so great that it makes sense to have different classes for different input types (and not just overload the constructor and behave differently for different inputs). Again, I did this for comparison, and it's much faster to have special cases handled in their own classes rather than case

s / if

in each function.

So what I would like to do is hide most of this implementation from junior developers, I don't want them to have to create three different overloads DoStuff

to handle different inputs. Ideally I would set up some type of callback with a #defines

and all they have to do is something like creating a named class DoStuff

and overloading the operator ()

and executing the function.

The problem I am facing is that the function DoStuff

that does this job is only templatized from <class C>

but itself scripted with help <class DataType>

and all I can’t figure out is how to go all around in a general way. For example, I cannot use template <class C<DataType>>

or template<template< class DataType> class C>

. It just won't compile.

Does anyone have a good trick to have a generic call, either a function or a functor (I don't care), with this nested template? Basically, I want something where I can write a generic function that doesn't care about the class holding the data, and calls it a mostly generic function that determines which class to use.

BigSwitch(CallBack,Inputs)
{
    switch(//something)
    {
    case 1: return CallBack(Class1<Type>(Inputs))
    case 2: return CallBack(Class2<Type>(Inputs))
    }
}

      

This way I can write one function BigSwitch

and other people will write CallBack functions.

Any ideas?


EDIT for clarification for Jalf:

I have two very similar classes, Class1

and Class2

, which basically represent the same data type, but the data store is significantly different. To make it more concrete, I use a simple example Class1

- a simple array, and Class2

looks like an array, but instead of storing in the memory are stored in a file (because it is too large to be placed in memory) so I'm going to call them MemArray

and FileArray

now. So let's say I want the sum of the arrays. I can do something like this

template <class ArrayType, class ReturnType>
ReturnType Sum(ArrayType A)
{
    ReturnType S=0;
    for (int i=A.begin();i<A.end();++i)
    {
      S+=A[i];
    }
    return S;
}

      

But now I need a way to load real data into an array. If it is a memory based array I would do this

MemArray<DataType> M(pData);

      

and if it is file-baaed i would do this

FileArray<DataType> F(filename);

      

and both of these calls are valid (since the compiler generates both code paths at compile time)

double MS=Sum<MemArray<DataType>,double>(M);
double FS=Sum<FileArray<DataType>,double>(F);

      

This all assumes that I know what the DataType is, but for a file-based array, I might not know the data type until I open the file and ask for a header to see what data is in the array.

double GetSum(char* filename)
{
    int DataTypeCode=GetDataTypeCode(filename);
    switch (DataTypeCode)
    {
    case 1: return Sum<FileArray<int>,double>(FileArray<int>(filename));
    case 2: return Sum<FileArray<double>,double>(FileArray<double>(filename));
    }
}
template <class DataType>
double GetSum(DataType* pData)
{
    return Sum<MemArray<DataType>,double>(MemArray<DataType>(pData));
}

      

This all works, but it requires writing two overloaded functions GetX

and a function X

for everything I would like to do. functions GetX

are basically the same code every time except the called one X

. So I would like to write something like

double GetX(CallBackType X, char* filename)
{
    int DataTypeCode=GetDataTypeCode(filename);
    switch (DataTypeCode)
    {
    case 1: return X<FileArray<int>,double>(FileArray<int>(filename));
    case 2: return X<FileArray<double>,double>(FileArray<double>(filename));
    }
}
template <class DataType>
double GetX(CallBackType, DataType* pData)
{
    return X<MemArray<DataType>,double>(MemArray<DataType>(pData));
}

      

so I can call

GetX(Sum,filename)

      

and then when someone wants to add a new function, all they have to do is write the function and call

GetX(NewFunction,filename)

      

I'm just looking for a way to write my overloaded functions GetX

and my functions X

so that I can abstract the input / storage path from the real algorithms. This is usually not a hard problem, I just have problems because the function X

contains a template argument that is itself templated. template<class ArrayType>

also has a hidden one ArrayType<DataType>

hidden there. The compiler is not happy with this.

+1


a source to share


2 answers


Focusing on the original part of your question (why aren't you just using inheritance):

The usual way of compile time polymorphism and giving access to derived class members through the base class is through CRTP .

template <typename T>
class IInterface {
  void DoStuff() {
    void static_cast<T*>(this)->DoStuff()
  }
};

class Class1 : IInterface<Class1> {
  void DoStuff(){...}
}

      

Will this solve your problem?

Edit: By the way, I'm glad I can help, but next time try to structure your question a little more.



I didn't really know what you were asking, so it was just a punch in the dark based on the first three lines of your question.;)

You never explain what you are trying to achieve, just what looks like a broken workaround. Start by posing a problem, as this is what we really need to know. You can then provide information on your current workarounds. And add some context when posting your code. Where is DoStuff () called from and why should junior developers define them? (You've already done that, haven't you?)

What would junior developers say with this code in the first place?

And it's confusing that you are providing specific cases (1 and 2) but not the switch statement itself (// something)

Next time you will get much more (and better and faster) answers if you try to make it easier to answer the question. :)

+3


a source


Regarding your question about "generic callback", you can use boost :: function , but mostly uses virtual functions under the covers (it may not be the case, but at least a similar concept), so the performance difference you are looking for is , won't (in fact, the boost :: function will probably be slower due to heap allocation).



0


a source







All Articles