Is it possible to declare template of template?

Viewed 99

I have objects of type 'value' from OCaml in C++ (they are provided by some integration channel, but it is offtopic). This object contains OCaml data of some type (primitive: int, long... or structural). It can be converted to a C++ object, from OCaml int to C++ int, etc by some provided by "caml/mlvalues.h" functions like Int_val (Long_val, Bool_val ...).

I wrapped functions from "caml/mlvalues.h" by some template function T to<T>(value x) in Caml::Value namespace to improve readability. (Caml::Value::to<bool> better then Bool_val).

caml.h:

namespace Caml::Value {
  template<typename T> struct CannotConvertTo { };
  template<typename T> T to(value x);

caml.cpp:

namespace Caml::Value {
  template<typename T> T to(value x) {
    if (is_enum<T>::value) {
      return static_cast<T>(to<int>(x));
    }

    throw CannotConvertTo<T>();
  }
  
  template<> int to<int>(value x) {
    return Int_val(x);
  }

  template<> bool to<bool>(value x) {
    return Bool_val(x);
  }
}

Also 'value' can contain some structure and we can read fields of this structure by the function Field(value, index). And I trying to implement some generic implementation to convert the 'value' to tuple.

  template<> tuple<T1, T2> to<tuple<T1, T2>>(value x) {
    return make_tuple<T1, T2>(
      to<T1>(Field(x, 0)),
      to<T2>(Field(x, 1))
    );
  }

Of course, it is an uncompilable code because of unknown types T1 and T2. How to implement to<tuple<T1, T2>>()? Is it possible to declare something like a template of a template? Like:

template<typename T1, typename T2> 
template<> tuple<T1, T2> to<tuple<T1, T2>>(value x) {
...
}
1 Answers

You can forward the operation from a function template to a class template and specialise the latter, leaving the former fully generic.

// base case: conversion disallowed
template <typename K>
struct convert_to
  { static K convert_to(value) = delete; };

// convert to specific types                                
template <> struct convert_to<int> 
  { static int convert(value); };
template <> struct convert_to<bool> 
  { static bool convert(value); };
template <typename L, typename R> struct convert_to<std::pair<L, R>> 
  { static std::pair<L, R> convert(value); };

// function template, never specialised
template <typename K> K to(value x) 
  { return convert_to<K>::convert(x); } 
Related