#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
#include <functional>

template <class T, class U>
class Conversion {
public:
    Conversion(const std::function<U(const T&)>& f) : f(f) {}
    U convert (const T& v) const { return f(v); }
private:
   std::function<U(const T&)>  f;
};
template <class T>
class Conversion<T,T> {
public:
    T convert (const T& v) const { return v; }
};


template <class T>
class ConvertFunctions0 : public Conversion<T,T> {};

template <class T, class V1>
class ConvertFunctions1 : public Conversion<T,T>, public Conversion<T,V1> {
public:
  ConvertFunctions1(std::function<V1(const T&)> f1) : Conversion<T,V1>(f1) {}
};

template <class T, class V1, class V2>
class ConvertFunctions2 : public Conversion<T,T>, public Conversion<T,V1>, public Conversion<T,V2> {
public:
  ConvertFunctions2(std::function<V1(const T&)> f1, std::function<V2(const T&)> f2) 
  : Conversion<T,V1>(f1), Conversion<T,V2>(f2) 
  {}
};

template <class T, class CF>
class MultiUnitValue {
public:
   MultiUnitValue(T v, const CF& cf) : v(v), cf(cf) {}
   
   template <class U>
   U in() const
   {
      return cf.Conversion<T,U>::convert(v);
   }

private:
   T v;
   CF cf;
};

int main(){
  auto f1 = [](int i){return i*2.54;};
  auto f2 = [](int i){ std::stringstream ss; ss << i; return ss.str(); };
  typedef ConvertFunctions2<int, float, std::string> CF_f1_f2;
  MultiUnitValue<int, CF_f1_f2>  vv(1, CF_f1_f2(f1, f2));
  std::cout << vv.in<int>() << "\n";
  std::cout << vv.in<float>() << "\n";
  std::cout << vv.in<std::string>() << "\n";
  // std::cout << vv.in<long>() << "\n"; // error to compile
}