Templates in FPL?

Marcin 'Qrczak' Kowalczyk qrczak@knm.org.pl
18 May 2001 19:11:21 GMT


Fri, 18 May 2001 11:25:14 +0200, Jerzy Karczmarczuk <karczma@info.unicaen.fr> pisze:

> Always when somebody mentions templates in presence of a True
> Functionalist Sectarian, the reaction is "What!? Abomination!!".

They aren't that wrong, but they have some problems:

* It's not specified what interface they require from types to be
  instantiated to.

* The whole implementation must be present in a public header file.
  Well, there is the 'export' keyword, but no compiler implements it.
  It follows that all things used by implementation of a template must
  be included too. And compilation time of a large project is larger
  than necessary.

* They introduce very complex rules about name lookup (environment
  in which a specialized template is compiled is a weird mix of
  environments of the point of definition and point of usage of the
  template), deduction which overloading to use (with choosing the
  candidate according to partial ordering of better fitting), deduction
  of template types and what partial specialization to use, complicated
  by the fact that there are complex rules of implicit conversions.
  
  Templates don't obey a Haskell's rule that adding code doesn't change
  the meaning of previously valid code and can at most introduce an
  ambiguity which is flagged as error.

* Types can't be deduced from the context of usage. For example
  handling the empty set or monadic 'return' would require either
  spelling the type at each use or introducing another type and
  deferring deduction of the real type until an operation is performed
  with a value of a known type.

* Since they are similar to macros, they tend to give horrible error
  messages which mentions things after expansion. Here is what I
  once got:

mico-c++ -Wall -I.   -c serwer.cc -o serwer.o
serwer.cc: In method `void Firma_impl::usun(const char *)':
serwer.cc:92: `struct __rb_tree_iterator<pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *>,const pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *> &,const pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *> *>' has no member named `second'
serwer.cc:93: no matching function for call to `map<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *,less<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> > >,__default_alloc_template<true,0> >::erase (__rb_tree_iterator<pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *>,const pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *> &,const pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *> *> &)'
/usr/include/g++/stl_map.h:156: candidates are: map<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *,less<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> > >,__default_alloc_template<true,0> >::erase<string, Katalog *, less<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> > >, alloc>(__rb_tree_iterator<pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *>,pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *> &,pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *> *>)
/usr/include/g++/stl_map.h:157:                 map<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *,less<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> > >,__default_alloc_template<true,0> >::erase<string, Katalog *, less<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> > >, alloc>(const string &)
/usr/include/g++/stl_map.h:158:                 map<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *,less<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> > >,__default_alloc_template<true,0> >::erase<string, Katalog *, less<basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> > >, alloc>(__rb_tree_iterator<pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *>,pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *> &,pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *> *>, __rb_tree_iterator<pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *>,pair<const basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> >,Katalog *> &,pair<const basic_string<char,string_char_traits<char>,
    __default_alloc_template<true,0> >,Katalog *> *>)
make: *** [serwer.o] Error 1


They also have some advantages over mechanisms available in Haskell:

* A templatized class can contain types, values with arbitrary types,
  other templates etc. so it's easy to have parametrization of all
  things by types. Haskell requires fundeps, dummy arguments and
  local quantifiers to handle these things - sometimes it's not nice.

* A template can be parametrized by values of primitive types (by
  expressions using builtin operations which can be evaluated at
  compile time). Yes, it's ugly that types and operations don't have
  equal rights, but it's sometimes useful.

* A template is in practice guaranteed to be specialized to used types,
  so they don't have a performance overheads over non-templatized
  variants. My not-quite-done-right attempt at inlining dictionary
  functions in ghc is a step in this direction, as is the proposal of
  export-unfolding-and-specialize-but-not-necessarily-inline. I hope
  that SimonPJ will sort this out.

-- 
 __("<  Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/
 \__/
  ^^                      SYGNATURA ZASTĘPCZA
QRCZAK