Templates
Feb 24, 2016 at 10:07pm UTC
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 Feb 24, 2016 at 10:10pm UTC
Feb 25, 2016 at 2:03am UTC
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;
}
Feb 25, 2016 at 8:18am UTC
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.