template processor. How to do ?

Hello,

I would like to créate a sort of Data processing template. But i would like my Processor type can be used as Class or Class pointer...

How can i do to compile this main code ?
How can i know in process() function of template DataProcessor if i had to use "." or "->" ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <vector>

template<typename T, typename P> class DataProcessor {
  P mProcessor;
  std::vector<T> mData;

public:
  void push_back(const T& data) {
    mData.push_back(data);
  }

  void set(const P& processor) {
    mProcessor = processor;
  }

  P& get() {
    return mProcessor;
  }

  void process() {
    for (typename std::vector<T>::iterator it = mData.begin(); it != mData.end(); ++it) {
      mProcessor.process(*it);
    }
  }
};

class PrintData {
  std::string mPrefix;
public:
  
  void prefix(std::string prefix) {
    mPrefix = prefix;
  }

  void process(int i) {
    std::cout<<mPrefix<<" : "<<i<<std::endl;
  }
};

int main() {
  DataProcessor<int, PrintData> p1;
  p1.get().prefix("prefix");
  p1.push_back(1);
  p1.push_back(2);
  p1.push_back(3);
  p1.process();

  PrintData* pdata = new PrintData;
  pdata->prefix("prefix");
  DataProcessor<int, PrintData*> p2;
  p2.set(pdata);
  p2.push_back(1);
  p2.push_back(2);
  p2.push_back(3);
  p2.process();
}


Here is the evident compilation error :

1
2
3
4
$ g++ -o main main.cc
main.cc: In member function ‘void DataProcessor<T, P>::process() [with T = int, P = PrintData*]’:
main.cc:56:   instantiated from here
main.cc:23: error: request for member ‘process’ in ‘((DataProcessor<int, PrintData*>*)this)->DataProcessor<int, PrintData*>::mProcessor’, which is of non-class type ‘PrintData*’

What's wrong with:
1
2
3
4
PrintData* pdata = new PrintData;
pdata->prefix("prefix");
DataProcessor<int, PrintData> p2;
p2.set(*pdata);

The copy of PrintData.
You copy it all over the place, why not there too?
For typename T if i use int* this is to avoid copy of int (usefull if int is a bigger structure like a class) i would like the same behaviour with typename P.
You have to change the implementation. The best you can do is use some meta-programming construct to detect whether a pointer was passed in as the parameter and act accordingly. See Alexandrescu's Loki.
Ok thanks. I was afraid by a anwser of this kind... for now i will force to use Copy of P or a pointer.
The solution i have found is that. What does you think about it ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
template<typename T, typename P> class DataProcessor {
  P* mProcessor;
  bool mOwnProcessor;
  std::vector<T> mData;

  void deleteifown() {
    if (mOwnProcessor && mProcessor != NULL) {
      delete mProcessor;
      mProcessor = NULL;
    }
  }

public:
  DataProcessor() : mProcessor(NULL) {}

  ~DataProcessor() {
    deleteifown();
  }
  
  void set(const P& processor) {
    deleteifown();
    mProcessor = new P(processor);
    mOwnProcessor = true;
  }

  void set(P* processor, bool aquiere) {
    deleteifown();
    mProcessor = processor;
    mOwnProcessor = aquiere;
  }

  P& get() {
    return *mProcessor;
  }
  
  void push_back(const T& data) {
    mData.push_back(data);
  }
  void process() {
    for (typename std::vector<T>::iterator it = mData.begin(); it != mData.end(); ++it) {
      mProcessor->process(*it);
    }
  }
};
Last edited on
It's only the ownership of the processor that's parameterised. The interface allows you to specify at run-time whether DataProcessor owns the processor or not. But that's not a compile-time decision. It would only make sense to go further if you parameterised DataProcessor at compile-time.
Topic archived. No new replies allowed.