Scientific Programming 21 (2013) 43–61 43 DOI 10.3233/SPR-130362 IOS Press techniques for concept-based specialization

Bruno Bachelet a,b,∗, Antoine Mahul c and Loïc Yon a,b a Clermont Université, Université Blaise Pascal, LIMOS, BP 10448, F-63000 Clermont-Ferrand, France b CNRS, UMR 6158, LIMOS, F-63171 Aubière, France c Clermont Université, Université Blaise Pascal, CRRI, F-63000 Clermont-Ferrand, France

Abstract. In , software components are parameterized on types. When available, a static specialization mechanism allows selecting, for a given of parameters, a more suitable version of a generic component than its primary version. The normal C++ template specialization mechanism is based on the type pattern of the parameters, which is not always the best way to guide the specialization process: type patterns are missing some information on types that could be relevant to define specializations. The notion of a concept, which represents a set of requirements (including syntactic and semantic aspects) for a type, is known to be an interesting approach to control template specialization. For many reasons, concepts were dropped from C++11 standard, this article therefore describes techniques for declaring concepts, modeling relationships (meaning that a type fulfills the requirements of a concept), and refinement relationships (meaning that a concept refines the requirements of another concept). From a taxonomy of concepts and template specializations based on concepts, an automatic mechanism selects the most appropriate version of a generic component for a given instantiation. Our purely library-based solution is also open for retroactive extension: new concepts, relationships, and template specializations can be defined at any time; such additions will then be picked up by the specialization mechanism. Keywords: Generic programming, template specialization, concept-based overloading/specialization, template metaprogramming

1. Introduction ponents together at compile-time in an optimal man- ner, for instance, selecting the most appropriate code Generic programming focuses on providing param- for an algorithm based on the types bound to its tem- eterized software components, notably algorithms and plate parameters. data structures, as general as possible and broadly The normal C++ template specialization mechanism adaptable and interoperable [14], and as efficient as is based on the type pattern of the template parameters, non-parameterized components. Generic programming which is known to have many drawbacks. In this arti- relies on the notion of a generic component that is a cle, we propose a solution based on metaprogramming class, a function, or a method with parameters that are techniques to control template specialization with con- types or static values, instead of dynamic values as the cepts. It enables declaring a taxonomy of concepts that usual arguments of functions and methods. can be used to control template specialization: tem- With modern , no loss of efficiency oc- plate parameters are constrained by concepts (instead curs when the parameters of a generic component of type patterns) to define a specialization. At instantia- are bound at compile time, which makes generic pro- tion time, an automatic mechanism selects the most ap- gramming particularly adapted for scientific program- propriate version of a generic component based on the ming (e.g., [4,5,15,17,21]). When designing scientific concepts of the types bound to the template parameters. libraries with generic programming, template special- ization is a major concern as it allows assembling com- 1.1. Template specialization

*Corresponding author. Tel.: +33473405044; bruno.bachelet@ Similar to inheritance in object-oriented program- univ-bpclermont.fr. ming, which allows the specialization of classes, C++

1058-9244/13/$27.50 © 2013 – IOS Press and the authors. All rights reserved 44 B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization provides a mechanism to specialize generic compo- concept. The notion of a specialization between con- nents (called templates). At instantiation time, the cepts is called “refinement”: a concept that includes the selects a version, the primary or a special- requirements of another concept is said to refine this ized one, of a template based on the type pattern of the concept. types (or static values) bound to the parameters. Here is For instance, let us define the concept Integral a C++ example of a generic class, ArrayCompara- that captures the requirements of an integral number, tor, that allows comparing two arrays that contain N and the concept Numerical that captures the require- elements of type T. ments of any of number. One can state that type int models concept Integral, and concept Inte- template gral refines concept Numerical. class ArrayComparator { public: static int 1.3. Challenges with concepts run(const T * a, const T * b) { int i = 0; Concern (i) of the previous section is called “con- while (i Template Library). This leads to late error detections, class ArrayComparator { public: and thus to cryptic error messages [18]: for instance, static int let us declare the instantiation ArrayCompara- run(const char * a, const char * b) tor; if type X has no operator <, the error will { return memcmp(a,b,N); } be detected in method run, and not at the instantiation }; point. In some languages, specific features are used to support concepts for generic programming (e.g., type 1.2. Concepts classesinHaskell,deferredclassesinEiffel...[8]). In Java and C#, concepts are represented with in- In generic programming, instantiating a generic terfaces, but this approach restricts concepts to syntac- component raises two concerns: (i) how to ensure that tic requirements. Moreover, concepts bring more flex- a type bound to a parameter fulfills the requirements of ibility, because a type is not predestined to model any the generic component (e.g., any type bound to T must given concept. A type models a concept either implic- provide operators < and == in the ArrayCompara- itly (it fulfills automatically all the requirements of a tor class); (ii) how to select the most appropriate spe- concept, cf. “auto concepts” [9]), or explicitly (one has cialization of the generic component for a given bind- to declare the modeling relationship and to make ex- ing of the parameters (e.g., if type char is bound plicit how the type fulfills the requirements, cf. “con- to parameter T, then specialization ArrayCompara- cept maps” [9]). tor is selected; but how to make another Concern (ii) of the previous section usually deals type benefit from the same specialization). with “concept-based overloading” [11], as generic pro- To address these issues, the notion of a concept has gramming in C++ has a central notion of generic al- been introduced [3]. When a type is bound to a param- gorithms where function template specialization is es- eter of a generic component, it must satisfy a set of sential. In this article, we propose a solution for the requirements represented by a concept. These require- specialization of both function and class templates, so ments define syntactic constraints (i.e., on the we choose to use the term “concept-based specializa- of the type) and semantic constraints (i.e., on the be- tion”. This approach uses the partial specialization ca- havior of the type). When a type fulfills the require- pability of templates that is only available for classes ments of a concept, it is said that the type “models” the in C++. Therefore, this solution is basically designed B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization 45 for class template specialization, but is fully usable for be considered to be full concepts, as some features are function template specialization (as explained in Sec- missing. The long-term goal of this extension is to pro- tion 3.2, the specialization process of a function tem- pose a complete definition of concepts. plate can be easily delegated to a class template). A library-based emulation of C++0x concepts, The goal of concept-based specialization is to con- called the Origin Concept library, has also been devel- trol the specialization of generic components with oped based on new features of C++11 [19]. The pri- concepts rather than type patterns. By type pattern, mary goal of this solution is to provide a uniform inter- we mean a type or a parameterized type (e.g., T* face to defining and using concepts, but no new tech- or vector), or a template template parameter nique is proposed for concept-based specialization as [23] (e.g., template class U). Spe- it favors the ’s enable_if approach [13]. cialization based on type patterns can lead to ambigui- 1.4. Proposal ties (the compiler cannot decide between two possible specializations) or false specializations (the compiler In this article, a solution focused on the concept- selects an unintended specialization), as explained in based specialization aspect only is proposed. Due to Section 2. Furthermore, the extensibility of specializa- portability concerns, our goal is to provide a purely tion based on type patterns is limited: to control the library-based solution that could be used with any stan- specialization of a template for a new type (i.e., a type dard C++ compiler, and no need of an additional tool. that was not considered in the specialization process The proposed technique enables declaring concepts, before), a new specialization often needs to be defined modeling relationships, and refinement relationships. (unless the type already matches the type pattern of a Once a taxonomy of concepts has been declared, it can suitable specialization). be used to control the specialization of templates: to Several attempts have been made to represent con- define a specialization, concepts (instead of type pat- cepts in C++. On one hand, implementations for con- terns) are used to constrain parameters. At instantia- cept checking have been proposed, mainly to ensure in- tion time, the most appropriate version of a template is terface conformance of types bound to template param- selected based on the concepts modeled by the types eters [16,18]. On the other hand, an implementation for bound to the parameters: a metaprogram determines, concept-based specialization has been proposed [13]. for each one of these types, the most specialized con- In this solution, the specialization is based on both the cept to consider for this instantiation. SFINAE (substitution failure is not an error) principle Even if the proposed technique does not detect di- [2] and a mechanism to answer the question “does type rectly concept mismatches to provide more under- T model concept C?” (through the enable_if tem- standable error messages, it needs to perform some plate). However this approach may still lead to ambi- checking on concepts to lead the specialization pro- guities.1 cess. The checking is only based on “named confor- More recently, an extension of the C++ language mance” [16] (i.e., checking on whether a type has to support concepts [7,9] has been proposed to be in- been declared to model a given concept), and does not cluded into the C++ standard [10]. This extension is consider “structural conformance” (i.e., checking on available within the experimental compiler Concept- whether a type implements a given interface). GCC [9,12], and is also implemented as Concept- One key idea of generic programming is to express Clang in Clang, a C language family front-end for the components with minimal assumptions [14], therefore our solution is open for retroactive extension: LLVM compiler [22]. The inclusion of concepts has been deferred from C++11 standard, and a new exten- • A new concept or a new relationship (model- sion, Concepts Lite [20], has been designed and im- ing or refinement) can be declared at any time. plemented as a branch of GCC 4.8. This extension in- The declaration of such relationships is distinct troduces “template constraints”, a.k.a. “concepts lite”, from the definition of types and concepts, con- which is a subset of concepts that allows the use of trary to class inheritance and interface implemen- predicates to constrain template parameters. It is un- tation that have to be declared with the definition deniably an improvement on existing solutions to con- of classes. trol template specialization, but concepts lite can not • A new specialization based on concepts can be defined at any time, but only for templates that 1As explained in Boost documentation: http://www.boost.org/ have been prepared for concept-based specializa- doc/libs/release/libs/utility/enable_if.html. tion. 46 B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization

Section 2 discusses several issues encountered with 2.1. Specialization based on type patterns template specialization, and shows how concepts can be used to bypass most of them. Section 3 presents As an example, we propose to develop a generic template metaprogramming techniques for concept- class, Serializer, to store the state of an object based specialization, and an example using our library- into an array of (the “deflate” action), or to re- based solution. Section 4 reports the compile-time per- store the state of an object from an array of bytes (the formance of the library depending on the number of “inflate” action). The primary version of the template, concepts and the number of relationships (modeling which makes a bitwise copy of an object in memory, is and refinement) declared in a program. The full source defined as follows. code of the library and of the examples is available for download.2 template class Serializer { public: static int 2. Issues with template specialization deflate(char * copy, const T & object); static int This section presents several issues that may occur inflate(T & object, const char * copy); }; with template specialization based on type patterns, and how they can be addressed with concepts: This version should not be used for complex objects, (i) Some types that can be considered somehow sim- such as containers, where the internal state may have ilar (e.g., with a common subset of operations in their pointers that should not be stored (because these ver- interface) could be bound to the same specialization of sions of the deflate and inflate actions would lead to a template, but if they have no type pattern in common, memory inconsistency after restoring). Let us define a several specializations must be defined. specialized version of Serializer for the sequence (ii) A specialization based on type patterns may lead containers of the STL (Standard Template Library), to false specialization (i.e., an unintended specializa- such as vectors and lists. tion), because a type pattern can be insufficient to cap- ture the requirements that a template needs for a pa- template rameter. class CONTAINER> Smaragdakis [16] and Järvi et al. [13], that use con- class Serializer< CONTAINER > { public: cepts to control template specialization in C++ are dis- static int cussed in this section. Refinement relationships appear deflate(char * copy, const to be necessary to address another issue: CONTAINER & container); (iii) A type can possibly be bound to different spe- static int cializations of a template, when it models concepts that inflate(CONTAINER & container, constrain different specializations. If there is no clear const char * copy); }; ordering between these concepts, to choose one spe- cialization is not possible. For this specialization, parameter CONTAINER is The solution presented in this paper allows concept- constrained with the type pattern of the STL sequence based specialization for both function and class tem- containers: they are generic classes with two parame- plates, but it is basically designed for class template ters, the type T of the elements to be stored, and the specialization, because, as detailed in Section 3, it uses type ALLOC of the object used to allocate elements. the partial specialization capability of templates that Now, let us consider associative containers of the is not available for functions. However, concept-based STL, such as sets and maps. Their type pattern is dif- overloading can easily be enabled: the function tem- ferent from the one of sequence containers (they have plate to be specialized calls a static method of a class at least one more parameter COMP to compare ele- template where the whole specialization process is de- ments), whereas sequence and associative containers fined with our approach (cf. Section 3.2 for details). Therefore, the discussion in this paper is illustrated have a common subset of operations in their interface with an example of class template specialization. that should allow defining a common specialization of Serializer. However, as specialization is based on 2Source code is available at: http://forge.clermont-universite.fr/ type pattern for now, another specialization of Seri- projects/show/cpp-concepts. alizer is necessary. B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization 47

Fig. 1. Taxonomy of concepts for the serialization example.

template ization for this concept could be defined. Therefore, class CONTAINER> class “similar” types with different type patterns could be Serializer< CONTAINER > bound to the same specialization. { [...] }; (ii) Concepts could avoid false specialization: with template specialization based on concepts, any tem- Notice that this specialization of Serializer is plate parameter could be constrained by a concept, and only suitable for sets, and not for maps, because their only types that model this concept could be bound to type pattern is different: maps have an additional pa- the parameter. This way, only the types that satisfy the rameter K for the type of the keys associated with the requirements of a specialization could be considered. elements of the container. The specialization Seri- For the example of serialization discussed here, alizer< CONTAINER > Fig. 1 proposes concepts and their relationships. The is necessary for maps, whereas maps and sets have SingleObject and STLContainer concepts are a common subset of operations in their interface and defined to provide two specializations for Serial- should share the same specialization. izer: one based on bitwise copy, and another one The specialization for sets has been written hav- based on the common subset of operations shared by ing only STL associative containers in mind, but any all STL containers, respectively. As sequence and asso- type matching the same type pattern can be bound to ciative containers are of different natures, one can think the specialization. Thus, there could be an unintended of different ways of optimizing the serialization opera- match. For instance, the std::string class of the tions. For this reason, the STLContainer concept is C++ is an alias for a type that matches refined into the STLSequence and STLAssocia- the type pattern of sets: tive concepts to provide specializations of Seri- alizer for sequence containers and associative con- std::basic_string< char, tainers respectively. std::char_traits, std:: > 2.2. Specialization based on concepts The first two issues presented in the introduction of the section have been illustrated here. They could be Existing solutions for concept-based specialization addressed with concepts: in C++ [13,16] are discussed here. They use concepts 48 B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization to guide the specialization of templates, and enable ad- The Dispatcher template goes through all the dressing the two first issues presented in the introduc- concepts (in a well-defined order) until its parameter tion of the section. However, about the third issue, that T models a concept. The symbolic constant associated is to find the most appropriate specialization when a with the found concept is stored in the which attribute type can possibly be bound to several specializations, of Dispatcher. For instance, Dispatcher< the solutions presented here are not fully satisfactory. vector >::which is equal to IS_STL_ SEQUENCE. 2.2.1. Concept-based dispatch Compared to the version of the Serializer tem- The solution of McNamara and Smaragdakis [16] plate based on type patterns, there is an additional pa- implements concepts with “static interfaces” in C++, rameter with a default value that is the answer of the and proposes a “dispatch” mechanism to control tem- dispatcher for parameter T. This value is used rather plate specialization with concepts. The solution is than the type pattern of T to define the specializations based on the StaticIsA template that provides some of Serializer. This way, it is possible to provide a concept checking: StaticIsA::valid is specialization for any concept. For instance, Serial- true if T models concept C. Let us assume that izer< vector > instantiates in fact Seri- StaticIsA answers accordingly to the taxonomy of alizer< vector, IS_STL_SEQUENCE > concepts of Fig. 1 (see the source code for details). and matches the specialization for the STLSequence Here is an example of the dispatch mechanism for the concept. specialization of the Serializer generic class. Notice that the primary version of the template in-

enum { IS_SINGLE_OBJECT, IS_STL_CONTAINER, herits from a class that is only declared, the aim being IS_STL_SEQUENCE, that this version could not be instantiated. This way, IS_STL_ASSOCIATIVE, UNSPECIFIED }; compilation errors related to the fact that T has been instantiated with a wrong type occurs at the instantia- template struct Dispatcher { tion of Serializer, rather than inside the code of static const int which = StaticIsA::valid ? Serializer where it tries to call invalid operations IS_STL_ASSOCIATIVE on T. This solution avoids usual error messages that : StaticIsA::valid ? could be cryptic for the user [18]. IS_STL_SEQUENCE In this solution, a dispatcher (and dispatch rules) : StaticIsA::valid ? IS_STL_CONTAINER is defined for nearly each context of specialization : StaticIsA::valid ? (i.e., for each template that is specialized), which can IS_SINGLE_OBJECT quickly become tedious. A dispatcher can be reused, : UNSPECIFIED; but only between specialization contexts that are iden- }; tical (i.e., providing specializations based on the same template concepts). Moreover, to define a new specialization for struct ErrorSpecializationNotFound; a template implies to change its dispatch rules. A solu- tion where the dispatch rules, for each context of spe- template ::which> cialization, are automatically deduced from the mod- class Serializer eling and refinement relationships of the taxonomy of : ErrorSpecializationNotFound {}; concepts should be provided.

template 2.2.2. Concept-based overloading class Serializer The solution proposed by Järvi et al. [13] relies on { [...] }; template the enable_if template, which can be found in the class Serializer Boost Library [1], and the SFINAE (substitution fail- { [...] }; ure is not an error) principle [2], to provide some con- template trol on template specialization with concepts. The def- class Serializer enable_if { [...] }; inition of is recalled here. template class Serializer template { [...] }; struct enable_if_c { T type; }; B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization 49

template case, the specialization for concept SingleObject struct enable_if_c {}; is ignored. This solution keeps only the specializations con- template struct enable_if strained with a concept modeled by the type bound : enable_if_c {}; to T. If more than one specialization remain, the com- piler has to deal with an ambiguity: for instance, At instantiation time, if B is true, there is a nested vector models both STLContainer and type type inside enable_if_c, and thus inside STLSequence concepts. This ambiguity could be enable_if, if its parameter COND has an attribute avoided: concept STLSequence is more specialized value set to true. Let us assume that, for each con- than concept STLContainer, so the specialization cept C of the taxonomy of Fig. 1, a template is_C for STLSequence should be selected. is defined so is_C::value is true if T models 2.2.3. Conclusion concept C (see the source code for details). Here is an In this section, solutions have been presented to con- example of the use of enable_if for the specializa- trol template specialization with concepts. Concept- tion of the Serializer generic class. based dispatch allows considering refinement relation- ships, but the selection of the specialization is not au- template class Serializer tomatic and requires some specific code for each con- : ErrorSpecializationNotFound {}; text of specialization. At the opposite, concept-based overloading allows an automatic selection of the spe- template class cialization, but is not able to deal with ambiguities that Serializer > ::type> { [...] }; 3. A solution for concept-based specialization template class Serializer > terns to control template specialization, but to our ::type> { [...] }; knowledge, there is no solution that addresses all the issues brought up in the previous section. We propose template class here template metaprogramming techniques that en- Serializer > taxonomy to automatically select the most appropriate ::type> { [...] }; specialization of a template. Two main goals have guided our choices toward this template class library-based solution: to provide a fully portable C++ Serializer > ::type> cess the code), and to be open for retroactive extension { [...] }; (new concepts, relationships, and template specializa- tions can be defined at any time). The SFINAE principle is: if there is an error when binding types to the parameters of a template special- 3.1. Example ization, this specialization is discarded. For instance, the instantiation Serializer< vector > Let us consider the example of the Serializer implies an attempt to instantiate Serializer< generic class with our solution. In a first step, the tax- vector, typename enable_if< is_ onomy of concepts of Fig. 1 is defined: concepts and SingleObject< vector > >::type>,3 relationships (modeling and refinement) are declared. and because enable_if has no member type in this Then, the Serializer template is defined: first its primary version, and then its specializations for each 3typename is necessary in C++ to declare that the member concept. Details on the implementation of the library type is actually a type and not a value. are presented afterward. 50 B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization

Concepts declaration gnx_declare_concept(SingleObject); gnx_declare_concept(ComplexObject); gnx_declare_concept(STLContainer); gnx_declare_concept(STLSequence); gnx_declare_concept(STLAssociative);

Modeling and refinement relationships template <> struct gnx_models_concept : gnx_true {}; template <> struct gnx_models_concept : gnx_true {}; template <> struct gnx_models_concept : gnx_true {};

template struct gnx_models_concept,STLSequence> : gnx_true {};

template struct gnx_models_concept,STLSequence> : gnx_true {};

template struct gnx_models_concept,STLAssociative> : gnx_true {};

template struct gnx_models_concept,STLAssociative> : gnx_true {};

template <> struct gnx_models_concept : gnx_true {};

template <> struct gnx_models_concept : gnx_true {};

template <> struct gnx_models_concept : gnx_true {};

Template primary version struct SerializerContext;

template class Serializer : ErrorSpecializationNotFound {};

Template specialized versions template <> struct gnx_uses_concept : gnx_true {};

template class Serializer { [...] };

template <> struct gnx_uses_concept : gnx_true {};

template class Serializer { [...] };

template <> struct gnx_uses_concept : gnx_true {};

template class Serializer { [...] };

template <> struct gnx_uses_concept : gnx_true {};

template class Serializer { [...] }; B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization 51

Concepts are declared using gnx_ template declare_concept. The modeling and refinement struct gnx_type { typedef TYPE type; }; relationships are equally declared using metafunc- template tion gnx_models_concept. To control the special- struct gnx_value ization, a “specialization context” must be declared { static const TYPE value = VALUE; }; (SerializerContext in our example). Each spe- cialization of Serializer based on a concept must typedef gnx_value gnx_true; typedef gnx_value gnx_false; be declared and associated with the specialization SerializerContext context , using metafunction Template gnx_type represents a type and gnx_uses_concept . The most appropriate con- provides a type member type that is T itself. The T cept for a type bound to parameter is automatically same way, template gnx_value represents a determined by the gnx_best_concept macro and static value and provides an attribute value that is the stored in an additional parameter of the Serial- value V of type T. Based on template gnx_value, izer template, enabling template specialization based types gnx_true and gnx_false are defined to rep- on this parameter. resent the boolean values. The parameters of a metafunction, which are the pa- 3.2. Concept-based overloading rameters of the template representing the metafunc- tion, are assumed to be metadata (i.e., to be classes Our solution uses the partial specialization capa- with a member type or value). The “return value” bility of templates that is not available for functions of a metafunction is implemented with inheritance: the in C++. However, concept-based overloading of func- metafunction inherits from a class representing a meta- tions is possible with very few extra code. For instance, data. This way the metafunction itself has a member let us define function inflate that calls the in- type or value, and can be a parameter of another flate static method of Serializer; this function metafunction. Here are metafunctions necessary for benefits indirectly of the concept-based specialization the discussion of this section. of the class: template struct gnx_same : gnx_false {}; template inline int template inflate(T & object, const char * copy) struct gnx_same : gnx_true {}; { return Serializer::inflate(object,copy); } template struct gnx_if : ELSE {};

Some fundamental metafunctions are necessary to template implement our library. These generic classes are com- struct gnx_if : IF {}; mon in metaprogramming libraries (e.g., in the Boost MPL Library). A metafunction acts similarly to an or- Metafunctions usually need template specializa- dinary function, but instead of manipulating dynamic tion to fully implement their behavior. Metafunction values, it deals with metadata, meaning entities that gnx_same determines whether two types are identi- can be handled at compile time in C++: mainly types cal: gnx_same inherits from gnx_true and static integer values [1]. In order to manipulate if T1 and T2 are the same type, or from gnx_false equally types and static values in metafunctions, meta- otherwise. Thus, the value returned by metafunction 4 data are embedded inside classes, as follows. gnx_same is stored in its value attribute. Metafunction gnx_if acts similarly to the common 4 We chose to prefix all the metafunctions and macros of our li- if instruction: gnx_if inherits from A if gnx_ brary with “ ”. We also chose to use our own metafunctions T::value B A B instead of the ones of MPL for two reasons: we only need few of is true, or from otherwise. If and them and we want to be able to easily change their implementation represent metadata, then gnx_if inherits to optimize the compile time. the member nested in A or B. 52 B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization

3.4. Declaring concepts 3.4.2. Indexing concepts To design a list where concepts can be added at any This section describes how concepts are represented time, a mechanism for indexing the concepts is pro- and automatically indexed in order to be manipulated posed. The metafunction gnx_concept is defined: it afterward by metafunctions that control concept-based has one parameter that is an integer value, and it re- specialization. In our solution, an empty structure, de- turns the concept associated with this number. Adding fined using macro gnx_declare_concept, rep- a concept to the list is performed by the specialization resents a concept. For instance, struct STLCon- of the metafunction. tainer {}; declares concept STLContainer. template struct gnx_concept 3.4.1. Typelists : gnx_type {}; Concepts also need to be stored in a container, in or- template <> struct gnx_concept<1> der to be manipulated by metafunctions, for instance, : gnx_type {}; to determine the most appropriate concept for a tem- template <> struct gnx_concept<2> plate specialization. Notably, the “typelist” technique : gnx_type {}; [2,6], based on metaprogramming, allows building a [...] static linked list to store types, and can be defined as Indexing the concepts by hand is not acceptable, so follows. a solution to get the number of concepts already in the template list is needed. For this purpose, a preliminary version struct gnx_list { of the gnx_nb_concept metafunction is proposed. typedef CONTENT content; It goes through all the concepts in the list by increasing typedef NEXT next; an index until finding gnx_nil. }; template struct gnx_nb_concept struct gnx_nil {}; : gnx_if< gnx_same::type, Type gnx_nil represents “no type” (void is not gnx_nil>, used, as it could be a valid type to be stored in a list), gnx_value, and is used to indicate the end of a list. For instance, gnx_nb_concept > {}; to store the STLSequence and STLAssociative concepts in a list: For an automatic indexing of the concepts, one typedef would use the return value of metafunction gnx_nb_ gnx_list< STLSequence, concept to determine the next index to assign to a gnx_list > mylist1; template <> struct Common operations on linked lists can be defined gnx_concept::value+1> : gnx_type {}; on typelists [2]. For instance, to add concept STLCon- tainer in the previous list: template <> struct gnx_concept::value+1> typedef gnx_list : gnx_type {}; mylist2; [...] However, typelists are too static for our needs: in the previous example, list mylist1 cannot be modified However, this solution does not work, because using to add a type, so a new list mylist2 has to be cre- gnx_nb_concept<> infers that gnx_concept ated instead. In the following section, a solution is pro- is instantiated from gnx_concept<0> to gnx_ posed to build a list of concepts that can be modified concept, where N is the number of in- at compile time to add new concepts, without changing dexed concepts. Due to this fact, specializing gnx_ the identifier of the list. Typelists will nevertheless be concept for STLContainer and STLSequence useful in our solution for several metafunctions where in the previous example is not possible, because operations for merging and searching lists of concepts gnx_concept has already been instantiated are necessary. based on the primary version of gnx_concept.To B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization 53 eliminate this flaw, an additional parameter, called 3.5. Modeling and refinement relationships here “observer”, is added to both metafunctions gnx_ concept and gnx_nb_concept. This section describes how modeling and refine- ment relationships are represented to build a tax- template onomy of concepts, and presents several metafunc- struct gnx_concept : gnx_type {}; tions to get useful information from a taxonomy. Modeling relationships, between a type and a con- template cept, and refinement relationships, between two con- struct gnx_nb_concept : gnx_if< gnx_same gnx_models_concept metafunction. ::type, gnx_nil>, template , class CONCEPT> gnx_nb_concept struct gnx_models_concept : gnx_false {}; > {}; The primary version of the template returns false, The idea is to provide a different observer each time and the relationships are declared through specializa- the concepts need to be counted to determine the next tions of the template: if type X models concept C index to assign to a new concept: the new concept itself (or concept X refines concept C), then specialization will be the observer. With this solution, counting the gnx_models_concept must return true. OBS concepts with observer induces the instantiation template <> struct gnx_models_concept of gnx_concept, so any specialization : gnx_true {}; for index N+1 with an observer other than OBS is still possible. Finally, concepts are indexed as follows. Notice that gnx_models_concept provides an answer for a direct relationship only. If a type T mod- template struct els a concept C1 that refines a concept C2, this meta- gnx_concept function returns false for a relationship between T and ::value+1, OBS> C2. Additional metafunctions, necessary in our solu- : gnx_type {}; tion to find any relationship between a type and a con- cept (or between two concepts), are briefly presented template struct gnx_concept below (see the source code for details). ::value+1, OBS> • Metafunction gnx_direct_concepts : gnx_type {}; provides a list (using the typelist technique) of [...] all the concepts directly modeled by a type (or refined by a concept) X. It goes through all the X To declare a concept in a single and easy instruction, concepts using their index, and checks whether models (or refines) each concept using metafunc- as presented in the example at the start of the section, tion gnx_models_concept. Assuming that to the gnx_declare_concept macro is defined. retrieve a concept from its index (i.e., to call meta- function gnx_concept) is a constant time oper- #define gnx_declare_concept(CONCEPT) \ struct CONCEPT {}; \ ation, metafunction gnx_direct_concepts \ requires O(n) operations, where n is the number template struct \ of concepts declared in the program. gnx_concept \ • Metafunction gnx_all_concepts pro- ::value+1, OBS> \ vides a list of all the concepts directly or indi- : gnx_type< CONCEPT > {} rectly modeled by a type (or refined by a con- cept) X. It calls gnx_direct_concepts to To conclude, the gnx_nb_concept metafunc- list the concepts directly related to X, and recur- tion requires O(n) operations, where n is the num- sively gets all the concepts related to each one ber of concepts already declared in the program. of the direct concepts. This metafunction requires 2 Hence, at compile time, indexing n concepts requires O(n + rn) operations, where r is the number of n 2 O( i=1 i) = O(n ) operations. modeling and refinement relationships declared 54 B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization

in the program: at worst, all the n concepts are a type that represents the context of a given template asked for their direct concepts (i.e., a call to meta- specialization. Each template that uses specialization function gnx_direct_concepts), which re- based on concepts requires its own context. quires O(n2) operations; to build the final list, at There are two main reasons for this notion of a spe- worst all the r relationships are considered, and cialization context: (i) as seen previously, metafunction each time the list of the currently found concepts gnx_nb_concept, called by many metafunctions, is merged with the list of the newly found con- requires an observer to perform correctly and to allow cepts, which requires O(rn) operations (at worst defining new concepts at any time, and this observer 2n operations are necessary for the merging, as it will be the specialization context; (ii) as explained in avoids duplicates). the next section, it is necessary to known which con- • Metafunction gnx_matches_concept cepts are of interest for a given specialization context returns whether a type (or a concept) X models (or (i.e., which concepts are involved in the specialization refines) a concept C, directly or indirectly. This control), and we want a library-based solution compli- metafunction searches for C in the list of concepts ant with the C++ standard, so each one of these con- provided by metafunction gnx_all_concepts cepts must be associated with the context using the and requires O(n2 + rn) operations: O(n2 + rn) gnx_uses_concept metafunction. operations to build the list, and O(n)forthe template <> struct search. gnx_uses_concept 3.6. Specialization based on concepts : gnx_true {}; In our example, the SerializerContext con- This section explains how to declare template spe- text has been declared for the specialization of Seri- cializations based on concepts and how the “best” alizer. Among others, concept STLContainer is specialization is automatically selected at instantiation used to define a specialization of Serializer,so time. gnx_uses_concept is specialized (the same way 3.6.1. Declaring specializations as gnx_models_concept) to specify that concept With our solution, controlling the specialization of STLContainer is used in the SerializerCon- a template with concepts that constrain one of its pa- text context. rameters implies an additional parameter. In the exam- 3.6.2. Selecting the best specialization ple, class Serializer has initially one parameter T, Based on the list of concepts declared in a special- and based on different concepts that types bound to T ization context, and a taxonomy of concepts, meta- might model, several specializations of Serializer function gnx_contextual_concept determines must be provided. For this purpose, an extra parameter the “best” concept for a type T, meaning the most spe- is added to Serializer. cialized concept that T models and that is of interest for the context of specialization. template If we consider the taxonomy of concepts of Fig. 2, class Serializer and a context X that provides specializations for con- : ErrorSpecializationNotFound {}; cepts C1, C2 and C5 in this example, the following best concepts should be selected. This additional parameter is the most specialized concept that a type bound to T models and that is • For type A: concept C2, candidates are C1 and of interest for the specialization of Serializer. C2,butC2 is more specialized. This “best” concept is obtained using the gnx_best_ • For type B: no concept, there is no candidate in concept macro, which eases the call to metafunction the context’s list, gnx_nil is returned. • gnx_contextual_concept. For type C: concept C5, it is the only choice. • For type : concepts C1 or C5, both concepts #define gnx_best_concept(CONTEXT,TYPE) \ are valid (because D models both), and there is typename \ no relationship between them to determine that gnx_contextual_concept \ ::type one is more specialized than the other. The se- lected one depends on the implementation of Notice that metafunction gnx_contextual_ gnx_contextual_concept. In our solution, concept requires a “specialization context”, which is the concept with the highest index is selected. But B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization 55

Fig. 2. Example of best concept selection.

to avoid this arbitrary selection, one can add rela- of the targeted generic component), which provides tionships to the taxonomy of concepts, or can spe- high flexibility with minimal assumptions about com- cialize metafunction gnx_contextual_ ponents. concept for type D in context X. The selection of the best specialization is fully au- tomatic and safe as long as the modeling and refine- Metafunction gnx_contextual_concept goes through the list of all the concepts mod- tionships, declared manually with our solution, could eled directly or indirectly by type T (provided by be automated using a mechanism to check structural gnx_all_concepts), and selects the one that conformance, such as the “concept classes” introduced does not refine directly or indirectly any other con- in [19] (i.e., type traits that indicate whether a type cept in the list (using metafunction gnx_matches_ models a concept), or the StaticIsA template of concept X ) and that is declared in context .This Section 2.2.1: metafunction requires O(n2 + rn) operations: O(n2 + rn) operations to build the list, and O(n) to select the template best candidate (because gnx_all_concepts has struct gnx_models_concept already achieved all the necessary gnx_matches_ : gnx_value ::valid> {}; concept instantiations). 3.7.1. Pitfalls 3.7. Conclusion However, a few issues occur with our solution. First, the type pattern of any template specialized based on Two steps are necessary for concept-based special- concepts is altered: for each primary template param- ization with our solution: (i) to declare concepts and eter, an extra “hidden” parameter may be added to get modeling/refinement relationships in order to define a its best concept. For instance, users of the Serial- taxonomy of concepts; (ii) for each context of special- izer generic class could think that this template has ization, to declare the concepts that are used to control only one parameter, whereas it actually has two. the specialization. These steps are not monolithic, and Secondly, the notion of an observer, which is totally new concepts, relationships, and specializations can be hidden from the users of a template specialized based defined at any time (but before the first instantiation on concepts, has been introduced to bypass an instanti- 56 B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization ation problem with metafunction gnx_nb_concept formance with practical experiments. The initial imple- (cf. Section 3.4.2). However there are very specific sit- mentation of the library, that is presented in this paper, uations where the issue remains. For instance, the fol- is meant for understanding. Thus, a second version of lowing specialization may be troublesome. the library has been designed to optimize the compile time. Nevertheless, the metaprogramming techniques template <> class Serializer { [...] }; and how to use the library remain unchanged with this new version. To understand what kind of optimization It induces the full instantiation of Serializer has been performed, let us discuss on the following ex- that forces the default value of the hidden parame- ample of metafunction. ter to be instantiated (i.e., gnx_contextual_con- template struct plain_meta cept), which itself : gnx_if < test, branch1, forces gnx_nb_concept to be instantiated for ob- branch2 > {}; server SerializerContext. If concepts are added At instantiation time, both branch1 and after this code, another call to metafunction gnx_ branch2 are instantiated. But depending on the contextual_concept with context Serializ- value of test, only one of the two templates erContext will ignore the new concepts. Hence, actually needs to be instantiated. In our library, such one should avoid to instantiate gnx_contextual_ cases occur many times and lead to a lot of unneces- concept before the final use of the targeted template. sary instantiations. Metafunctions can be rewritten us- In our example, the full instantiation can be avoided as ing an intermediate template that hides the two possi- follows. ble branches of the conditional statement in separate template specializations of the template. Here is an optimized class Serializer version of the example that shows the technique that { [...] }; has been applied on all the metafunctions of the library. 3.7.2. Usage template struct _optimized_meta_; For the designers of generic libraries, using our so- lution for concept-based specialization helps improv- template struct optimized_meta ing extensibility and maintainability, as specialization : _optimized_meta_::value> {}; is controlled by concepts that are more relevant and ro- bust to guide the process than type patterns, and be- template cause retroactive extension is possible (i.e., a special- struct _optimized_meta_ : branch1 {}; ization, a concept, or a relationship, can be added at template any time, with no impact on existing code). struct _optimized_meta_ Designing a generic library with concept-based spe- : branch2 {}; cialization also offers new possibilities to end-users. The tests presented here have been performed with They have the opportunity to easily extend the tax- the optimized version5 of the library on an Intel Core onomy of concepts. For instance, if std::deque 2 Duo T8100 2.1 GHz with 3 GB of memory, and us- were not yet in the taxonomy, one can associate ing GNU G++ 4.3.4 (its template recursion limit set to it with concept STLSequence, and automatically, 1024). Instances with different numbers n of concepts std::deque benefits from the specialization of Se- and r of modeling/refinement relationships declared in rializer for STLSequence. Nonintrusively, the the whole program have been randomly generated (see users can also define new specializations for concepts the source code for details). Each compile time pre- that were not foreseen by the designers of the generic sented here is expressed in seconds and is the mean of library, but it requires some documentation on this li- compilations of 10 different instances. brary. Figure 3 reports the compile time, depending on n, for indexing concepts. As predicted by the theoretical performance analysis, there is a quadratic dependence 4. Compile-time performance on n (confirmed by a quadratic regression with a cor- relation coefficient6 R = 0.997). The theoretical performance of the metafunctions of our solution has been studied in this paper. We as- 5Optimized version 2011-08-25 was used for the experiments. sumed some operations of the compiler to be constant 6R = Pearson’s correlation coefficient; the closer to 1, the more time, so it is important to confirm the theoretical per- the regression fits the curve. B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization 57

Fig. 3. Compile time for indexing concepts (r = 100).

Fig. 4. Compile time for gnx_direct_concepts (50 instantiations, r = 100).

Figure 4 reports the compile time, depending on n, pendence on n, but the practical results show other- of 50 instantiations of metafunction gnx_direct_ wise, which we think is related to our assumption that concepts (which lists the concepts that a given type accessing a concept through its index (i.e., a call to or concept directly models or refines respectively). The gnx_concept) was constant time. It seems that to theoretical performance analysis predicted a linear de- find a specialization of a template, the compiler may 58 B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization require a number of operations dependent on the to- stantiations of gnx_direct_concepts represent tal number of specializations for this template. How- only one step of the whole compilation process. ever, this non-linear dependence is not so significant, Figures 5 and 6 report the compile time, depend- as the linear regression shows a correlation coefficient ing respectively on n and r, of 50 instantiations of R = 0.986 in the range of our experiments, and the in- gnx_contextual_concept (which determines

Fig. 5. Compile time for gnx_contextual_concept (50 instantiations, r = 300).

Fig. 6. Compile time for gnx_contextual_concept (50 instantiations, n = 80). B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization 59 the best concept for a type bound to a template param- dependence on r (confirmed with R = 0.989). eter). The performance of each intermediate metafunc- Our library has been tested successfully on several tion is not shown, as it is similar. As predicted by the compilers: GNU GCC from 3.4.5 to 4.4.3, Microsoft theoretical performance analysis, there is a quadratic Visual C++ 10, and Embarcadero C++ 6.20. Figures 7 dependence on n (confirmed with R = 1), and a linear and 8 report the time of the whole compilation pro-

Fig. 7. Whole compile time (with 30 instantiations of gnx_contextual_concept, r = 100).

Fig. 8. Whole compile time (with 50 instantiations of gnx_contextual_concept, n = 50). 60 B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization cess for those compilers, from indexing the concepts to our solution. Even if a quadratic dependence on the finding the best concepts for types bound to template number of concepts has been identified, the compile parameters, depending on n and r. Notice that we were time is reasonable for many applications: compiling not able to test all the instances with Embarcadero’s 50 specializations with 50 concepts and 250 model- compiler, due to a hard limitation of 256 levels in the ing/refinement relationships on an average computer template recursion. requires less than 5 seconds.

5. Conclusion Acknowledgements

This paper describes template metaprogramming The authors would like to thank the editor and the techniques to control the specialization of generic anonymous reviewers for their constructive comments components with concepts. As concepts are not part of that helped to improve the manuscript. the C++ language yet, a library-based solution is pro- vided to declare concepts and modeling/refinement re- lationships in order to define a taxonomy of concepts. References It relies on an automatic indexing of the concepts that allows a retroactive extension: at any time, new con- [1] D. Abrahams and A. Gurtovoy, C++ Template Metaprogram- ming: Concepts, Tools, and Techniques from Boost and Be- cepts and modeling/refinement relationships can be de- yond, Addison-Wesley, 2004. clared. [2] A. Alexandrescu, Modern C++ Design: Generic Program- The library also provides a mechanism to automat- ming and Design Patterns Applied, Addison-Wesley, 2001. ically select the most appropriate specialization of a [3] M.H. Austern, Generic Programming and the STL: Using template based on concepts. Specializations of generic and Extending the C++ Standard Template Library, Addison- Wesley, 1999. components can be defined by constraining template [4] B. Bachelet, A. Mahul and L. Yon, Designing generic algo- parameters with concepts rather than type patterns. At rithms for operations research, Software: Practice and Experi- instantiation time, a metafunction determines the most ence 36(1) (2006), 73–93. specialized concept, for a given specialization context, [5] C.G. Baker and M.A. Heroux, Tpetra, and the use of generic of any type bound to a template parameter, and thus programming in scientific computing, Scientific Programming 20(2) (2012), 115–128. guides the selection of the most appropriate specializa- [6] K. Czarnecki and U. Eisenecker, Generative Programming: tion. Our solution is invasive because an extra param- Methods, Tools, and Applications, Addison-Wesley, 2000. eter (invisible to the user) must be added to any tem- [7] G. Dos Reis and B. Stroustrup, Specifying C++ concepts, in: plate that is intended to be specialized based on con- Proceedings of POPL’06, ACM Press, 2006, pp. 295–308. cepts; but after the definition of the primary version of [8] R. Garcia, J. Järvi, A. Lumsdaine, J.G. Siek and J. Willcock, A comparative study of language support for generic program- the template, specializations based on concepts can be ming, in: Proceedings of OOSPLA’03, 2003, pp. 115–134. added non intrusively and retroactively. [9] D. Gregor, J. Järvi, J.G. Siek, B. Stroustrup, G. Dos Reis The retroactive extension enabled by the proposed and A. Lumsdaine, Concepts: Linguistic support for generic technique provides high flexibility with minimal as- programming in C++, in: Proceedings of OOPSLA’06, 2006, sumptions about the components: the coupling be- pp. 291–310. [10] D. Gregor, B. Stroustrup, J.G. Siek and J. Widman, Pro- tween a template and the types bound to its parameters posed wording for concepts (Revision 3), Technical Report only occurs at instantiation time, while the most appro- N2421=07-0281, ISO/IEC JTC 1, 2007. priate specialization is selected. However, because our [11] J. Järvi, D. Gregor, J. Willcock, A. Lumsdaine and J.G. Siek, goal was to provide a fully portable C++ code with no Algorithm specialization in generic programming: Challenges extra tool, we were not able to automate the identifica- of constrained generics in C++, in: Proceedings of PLDI’06, ACM Press, 2006. tion of the concepts that control the specialization of a [12] J. Järvi, M. Marcus and J.N. Smith, Programming with C++ given template. Therefore, the notion of a specializa- concepts, Science of Computer Programming 75 (2010), 596– tion concept is necessary and requires to explicitly de- 614. clare each concept that is involved in the control of a [13] J. Järvi, J. Willcock and A. Lumsdaine, Concept-controlled specialization. polymorphism, in: Lecture Notes in Computer Science, Vol. 2830, Springer-Verlag, 2003, pp. 228–244. To conclude, a theoretical performance analysis [14] M. Jazayeri, R. Loos, D. Musser and A. Stepanov, Generic and the performance of practical experiments have programming, in: Report of the Dagstuhl Seminar on Generic been presented to show the compile time overhead of Programming, 1998. B. Bachelet et al. / Template metaprogramming techniques for concept-based specialization 61

[15] U. Köthe, STL-style generic programming with images, C++ [20] A. Sutton, B. Stroustrup and G. Dos Reis, Concepts lite: Con- Report Magazine 12(1) (2000), 24–30. straining templates with predicates, Technical Report, N3580, [16] B. McNamara and Y. Smaragdakis, Static interfaces in C++, ISO/IEC JTC 1, 2013. in: First Workshop on C++ Template Programming, 2000. [21] T.L. Veldhuizen, Arrays in Blitz++, in: Lecture Notes in Com- puter Science, Vol. 1505, Springer-Verlag, 1998, pp. 223–230. [17] J.G. Siek, L.-Q. Lee and A. Lumsdaine, The Boost Graph Li- [22] L. Voufo, M. Zalewski and A. Lumsdaine, ConceptClang: an brary: User Guide and Reference Manual, Addison-Wesley, implementation of C++ concepts in clang, in: 7th ACM SIG- 2002. PLAN Workshop on Generic Programming, 2011. [18] J.G. Siek and A. Lumsdaine, Concept checking: Binding para- [23] R. Weiss and V. Simonis, Exploring template template pa- metric polymorphism in C++, in: First Workshop on C++ Tem- rameters, in: Lecture Notes in Computer Science, Vol. 2244, plate Programming, 2000. Springer-Verlag, 2001, pp. 500–510. [19] A. Sutton and J.I. Maletic, Emulating C++0x concepts, Science of Computer Programming 78 (2013), 1449–1469. Advances in Journal of Multimedia Industrial Engineering Applied Computational Intelligence and Soft

International Journal of Computing The Scientific Distributed World Journal Sensor Networks Hindawi Publishing Corporation Hindawi Publishing Corporation Hindawi Publishing Corporation Hindawi Publishing Corporation Hindawi Publishing Corporation http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014

Advances in Fuzzy Systems

Modelling & Simulation in Engineering

Hindawi Publishing Corporation Hindawi Publishing Corporation Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com

Submit your manuscripts at http://www.hindawi.com Journal of Computer Networks and Communications Advances in Artificial Intelligence Hindawi Publishing Corporation http://www.hindawi.com Volume 2014 Hindawi Publishing Corporation http://www.hindawi.com Volume 2014

International Journal of Advances in Biomedical Imaging Artificial Neural Systems

International Journal of Advances in Computer Games Advances in Computer Engineering Technology Software Engineering

Hindawi Publishing Corporation Hindawi Publishing Corporation Hindawi Publishing Corporation Hindawi Publishing Corporation Hindawi Publishing Corporation http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014

International Journal of Reconfigurable Computing

Advances in Computational Journal of Journal of Human-Computer Intelligence and Electrical and Computer Robotics Interaction Neuroscience Engineering Hindawi Publishing Corporation Hindawi Publishing Corporation Hindawi Publishing Corporation Hindawi Publishing Corporation Hindawi Publishing Corporation http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014 http://www.hindawi.com Volume 2014