Templates

I've never used templates much, although I do know how to do the basics with them. I'm making a class which takes one type of input and converts it into a different type (Processor<In,Out>). Specific versions of this will then be instantiated, e.g.
double -> string -> user made encrypted class
To do this, I'd have
1
2
3
4
5
double value;
Processor<double,string> p1;
string intermediary;
Processor<string,encrypted> p2;
encrypted final;

I would like to make a function that would look like this:
 
Link<double, encrypted>(value, p1, p2, final);
or more generically like this:
 
Link<A,H>(A,Processor<A,B>,Processor<B,C>,...Processor<G,H>,H);

and would work by having each class have a reference that refers to the output of the previous.
How would I make a function that takes two templated types and a variable amount of Processors with each one having the output type of the next's input type? Is this even possible?
Last edited on
How about this?

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>
#include <sstream>
#include <cassert>
#include <typeinfo>
#include <string>

class PolymorphicProducer{
public:
	virtual ~PolymorphicProducer(){}
};

template <typename T>
class Consumer{
protected:
	PolymorphicProducer *input;
public:
	Consumer(PolymorphicProducer *input): input(input){}
	virtual ~Consumer(){
		delete this->input;
	}
	T get_input();
};

template <typename T>
class Producer : public PolymorphicProducer{
public:
	virtual ~Producer(){}
	virtual T get_output() = 0;
};

template <typename T>
class InitialProducer : public Producer<T>{
	T data;
public:
	InitialProducer(const T &data): data(data){}
	virtual ~InitialProducer(){}
	T get_output() override{
		return this->data;
	}
};

template <typename T>
T Consumer<T>::get_input(){
	Producer<T> *input = dynamic_cast<Producer<T> *>(this->input);
	assert(input);
	return input->get_output();
}

template <typename SrcT, typename DstT>
class Processor : public Consumer<SrcT>, public Producer<DstT>{
public:
	Processor(PolymorphicProducer *input): Consumer<SrcT>(input){}
	DstT get_output() override{
		std::stringstream stream;
		stream << this->get_input();
		std::cout << typeid(SrcT).name() << " -> " << typeid(DstT).name() << std::endl;
		DstT ret;
		stream >> ret;
		return ret;
	}
};

template <typename T>
struct type_spec{};

template <typename DstT>
class Linker{
	Producer<DstT> *producer;
public:
	Linker(const DstT &data): producer(new InitialProducer<DstT>(data)){}
	Linker(Producer<DstT> *producer): producer(producer){}
	template <typename T2>
	Linker<T2> operator>>(const T2 &){
		return Linker<T2>(new Processor<DstT, T2>(this->producer));
	}
	template <typename T2>
	Linker<T2> operator>>(const type_spec<T2> &){
		return Linker<T2>(new Processor<DstT, T2>(this->producer));
	}
	Producer<DstT> *get(){
		return this->producer;
	}
};

template <typename T>
Linker<T> make_linker(const T &data){
	return Linker<T>(data);
}

int main(){
	auto linker = make_linker(7.4) >> type_spec<int>() >> type_spec<std::string>();
	auto producer = linker.get();
	std::cout << producer->get_output() << std::endl;
	delete producer;
}
That's a really clever solution, thanks. So that I fully understand how it all works, I'll see if I can write a version of that myself that works. I'll post here again if it doesn't work and I can't work out why.
Topic archived. No new replies allowed.