4.3 Generic Programming Using Templates

One can write ``templated'' code for Chares, Groups, Messages and other CHARM++ entities using familiar C++ template syntax (almost). The CHARM++ interface translator now recognizes most of the C++ templates syntax, including a variety of formal parameters, default parameters, etc. However, not all C++ compilers currently recognize templates in ANSI drafts, therefore the code generated by CHARM++ for templates may not be acceptable to some current C++ compilers

Since many modern C++ compilers24 require that the template definitions (in addition to the template declarations) be available in all sources which use them, you will need to include the templated Charm definitions in your header file. That is, given a module stlib, in addition to having a line #include "stlib.decl.h" in your header file (e.g. stlib.h), you also need the following lines towards the end of the file:

#define CK_TEMPLATES_ONLY
#include "stlib.def.h"
#undef CK_TEMPLATES_ONLY

This has the effect of including into the header file only those declarations which relate to templates. You will still need to include the file stlib.def.h again in your implementation sources (i.e., stlib.C) in order to pick up the rest of the (non-template-related) definitions. Note that for completely template-based libraries, this means that you might need to create an implementation file stlib.C when you otherwise wouldn't solely for the purpose of making sure that the non-template definitions in stlib.def.h are included and compiled.

The CHARM++ interface file should contain the template definitions as well as the instantiation. For example, if a message class TMessage is templated with a formal type parameter DType, then every instantiation of TMessage should be specified in the CHARM++ interface file. An example will illustrate this better:

  template <class DType=int, int N=3> message TMessage;
  message TMessage<>; // same as TMessage<int,3>
  message TMessage<double>; // same as TMessage<double, 3>
  message TMessage<UserType, 1>;

Note the use of default template parameters. It is not necessary for template definitions and template instantiations to be part of the same module. Thus, templates could be defined in one module, and could be instantiated in another module , as long as the module defining a template is imported into the other module using the extern module construct. Thus it is possible to build a standard CHARM++ template library. Here we give a flavor of possibilities:

module SCTL {
  template <class dtype> message  Singleton;
  template <class dtype> group Reducer {
    entry Reducer(void);
    entry void submit(Singleton<dtype> *);
  }
  template <class dtype> chare ReductionClient {
    entry void recvResult(Singleton<dtype> *);
  }
};

module User {
  extern module SCTL;
  message Singleton<int>;
  group Reducer<int>;
  chare RedcutionClient<int>;
  chare UserClient : ReductionClient<int> {
    entry UserClient(void);
  }
};

The Singleton message is a template for storing one element of any dtype. The Reducer is a group template for a spanning-tree reduction, which is started by submitting data to the local branch. It also contains a public method to register the ReductionClient (or any of its derived types), which acts as a callback to receive results of a reduction.

May 26, 2012
Charm Homepage