How to implement MultiUnitValue class using C++ TMP

Your solution was not "standard compliant", because member functions cannot be specialized in class template. This is because of general rule that functions cannot be partially specialized - so even "full" specialization of member function template is actually partial specialization because of not fully specialized class.


My solutions:

C++11 version

Your example with my version, I believe this is what you want:

int main(){
  auto f1 = [](int i){return i*2.54;};
  auto f2 = [](int i){ std::stringstream ss; ss << i; return ss.str(); };
  MultiUnitValue<int, float, std::string>  vv(1, 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
}

First of all - you need the special conversion base classes, for a single conversion, you will see in next code fragment that calling conversion via base class function causes that "non specified" conversion, like this for long will not compile.

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; }
};

And your class with using variadic templates:

template <class T, class... V> // V... means all desired conversions
class MultiUnitValue : private Conversion<T,T>, private Conversion<T,V>... {
// allowed conversion:         ^^^^^^^^^^^^^^^^^        ^^^^^^^^^^^^^^^^^^
public:
   MultiUnitValue(T v, const std::function<V(const T&)>&... f) : Conversion<T,V>(f)..., v(v) {}

   template <class U>
   U in() const
   {
      // this static assert is not needed - but just to show the message
      static_assert(std::is_base_of<Conversion<T,U>, MultiUnitValue<T,V...>>::value, 
                   "Not allowed conversion");

      // static_assert is not needed 
      // since if you MultiUnitValue does not derive from Conversion<T,U> 
      // - then this call will not compile too
      return this->Conversion<T,U>::convert(v);
   }

private:
   T v;
};

LVS example: http://liveworkspace.org/code/05b6ada146cc8f05d027a5536859a087

Version without variadic templates:

I also prepared solution without variadic templates, since VC++ still does not support them.

Second: the conversion and coversion limitation should be now in your T_to_U type.

With this approach usage will slightly inconvenient in the comparison to C++11 version:

int main(){
  auto f1 = [](int i){return i*2.54;};
  auto f2 = [](int i){ std::stringstream ss; ss << i; return ss.str(); };
  // next 2 lines differ from C++11 version
  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
}

The MultiUnitValue will be simpler than in your example, simpler even from my C++11 version, but the class CF will be much more complicated:

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;
};

The simple "helper" conversion classes will be identical as in C++11 version:

template <class T, class U>
class Conversion {
   ...
};
template <class T>
class Conversion<T,T> {
   ...
};

And the variadic template alternative in VC++ (and in old days of C++03):

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) 
  {}
};

As you can see - adding ConvertFunctions3, ConvertFunctions4 is not so big trouble...

Full example at ideone