Welcome to TTL (the Tiny Template Library)

Download

For discussions about the library, support or feature requests, use the mailing list.

If you'd like to contribute, please e-mail the project admin.

    Overview

    Installation

    Why?

    Design Notes

    Sample

    ttl::flg

    ttl::tup

    ttl::meta

    ttl::func

    ttl::var

    ttl::sig

Overview

The Tiny Template Library (TTL) is a C++ template library for generic programming. The main objective is to develop a lightweight practical alternative to some of the Boost components. TTL started as an experiment during the development of Notus, a GUI template library. TTL was heavily influenced by Boost. As much as possible we try to support the Boost interfaces and semantic. In most cases switching between Boost and TTL should be as easy as switching headers and namespaces. For example

#if defined(__USE_BOOST_VARIANT__)
# include "boost/variant.hpp"
# define VAR boost
#else
# include "ttl/var/variant.hpp"
# define VAR ttl::var
#endif
VAR::variant<int, char> v(1);

Note: the comments about boost and ttl reflect our experience with boost v1.31.0 and TTL v1.0.

Installation

Download

The whole library resides in headers files only. There is nothing to be built or installed, just copy the TTL files into one of you folders and and make sure that this folder is in the list of include folders in your compiler. You can then include TTL headers as in the following example.

#include "ttl/var/variant.hpp"

Why?

Why do we need an alternative? Well, just to have a choice... but there are some other reasons.

Design Notes

One of the main objectives is a compact and readable implementation. The library requires a relatively compliant compiler. As for now, we test TTL on two compilers, MSVC v7.1 and GCC v3.2.3. If you are still using MSVC v6.0, please come back after you get rid of it.

One definition

All classes have only one definition. For example if a definition compiles on MSVC v7.1 but not GCC 3.2.3, we'll choose to change the definition instead of adding #if defined(_MSC_VER) block.

Memory Management

TTL will never use global new/delete. All memory allocations/deallocations will be done with a user defined allocator or allocator defined in ttl::mem::memtraits class.

Exception Handling

TTL never throws an exception type other than derived from the ttl::exception class. The library will never attempt to catch all exceptions with catch(...). Internally the library is allowed to catch std::exception derived exceptions only.

Sample

To build the sample, make sure to set TTL_ROOT environment variable to your TTL folder. The sample is located in the samples/test folder.

When ran, it should output
int event: 10
double event: 2.3

The sample source code:

#if defined(_MSC_VER)
# include <crtdbg.h> //just to generate the memory dump
#endif

#include <iostream>
#include "ttl/func/function.hpp"
#include "ttl/sig/signal.hpp"
#include "ttl/var/variant.hpp"

namespace VAR=ttl::var;
namespace SIG=ttl::sig;
namespace SIG_CON=ttl::sig;
namespace FUNC=ttl::func;
typedef ttl::sig::connection connection;

//define event type
typedef VAR::variant<double, int> event;

struct event_visitor
{
   void operator()( int x )
   {
      std::cout<<"int event: "<<x<<"\n";
   }
   void operator()( double x )
   {
      std::cout<<"double event: "<<x<<"\n";
   }
};
void event_callback( event& ev )
{
   event_visitor v;
   VAR::apply_visitor(v, ev);
}

main()
{
#if defined(_MSC_VER)
   _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
   //create signal and connections
   SIG::signal< void (event&) > sig;
   connection con = sig.connect( event_callback );

   event ev(10);
   sig(ev);
   ev = 2.3;
   sig(ev);
   //disconnect
   con.disconnect();
}


ttl::flg

The flg namspace contains:

ttl::flg::flags

flags<> provides a type safe and generic way to handle collections of flags that are usually defined as bitfields

template< 
	typename T, //flags type usuall enumeration
	int Bits = sizeof(int)*8, //number of bits
	typename Holder = typename impl::bestfit::type //hold combinations of flags
	> struct flags
{
    typedef flags this_t;
    typedef T value_type;

    Holder f_;

    flags();
    flags( T f1, T f2, ... ); //intializes to f1|f2...
    
    Holder get_holder() const;
    
    bool test( const this_t& ) const;  //applies operator & to the holders
    bool test() const { return f_!=0; }
};


Usage

The flags<> class supports all bitwise and logical operatos.

//define some flags
struct winstyle
{
    enum type
    {
        CAPTION = 1,
        BORDER  = 1<<1,

        size = 2  //the last used bit
    };
};

typedef flags<winstyle> winstyle_flags;

void set_style( winstyle_flags style )
{
    if( style.test(winstyle::CAPTION) )
       ...do something about CAPTION
}

main()
{
    //initialize to winstyle::BORDER|winstyle::CAPTION
    winstyle_flags f(winstyle::BORDER, winstyle::CAPTION);
    set_style( f );
}

ttl::flg::flag_mapper

The TTL has a function for mapping one set of flags to another set. For instance if we need to map our winstyle flags to Win32 WS_CAPTION and WS_BORDER.

struct flag_map
{
    std::multimap< std::pair<winstyle_flags, int> > map;

    flag_map()
    {
        if( init_ )
        {
            init_ = false;  //initialize only once
            map_.insert( winstyle::CAPTION, WS_CAPTION );
            map_.insert( winstyle::BORDER, WS_BORDER );
        }
    }

    static bool init_;
    static map map_;
}

void set_style( winstyle_flags style );

main()
{
    flag_map map;

    set_style( winstyle_flags(winstyle::CAPTION,winstyle::BORDER)  )
}


void set_style( winstyle_flags style )
{
    //map our flags to Win32
    int style = ttl::flg::flag_mapper( flag_map.map_.begin(), flag_map.map_.end(), style );

    ::CreateWindow( ... style );  //use Win32 function with 'style' :)
}

ttl::tup

The tup namespace implements tuple. Its semantic is very similar to boost::tuples. However the implementation concepts are quite different.

The tup namespace contains the following symbols:

The maximum number of fields in tuple is defined by the TTL_MAX_TUPLE_PARAMS macro in config.h

Usage

ttl::tup::tuple<int, double> my_tuple;

my_tuple t(1, 2.3);
int n = ttl::tup:get<0>(t);
double x = ttl::tup:get<1>(t);
int l = ttl::tup::length<my_tuple>::value;
assert(l==2);

ttl::tup::element<N, Tuple>::type //type of the Nth element in Tuple.

ttl::meta

The meta namespace provides a small set of meta programming facilities.

ttl::meta::typelist

typelist is is a list of types that is specified as a set of template parameters. typelist<int, char> is a list of 'int' and 'char' types. typelist is very efficient. It is implemented as a plain set of typedefs. It doesn't have the overhead associated with nested templates as in some more popular implementations that use cons<H, cons<H, ...> > or duo<H, duo<H,...> > kind of techniques.
There is a number of meta functions that operate on typelists.

ttl::meta::get<L, N>

typedef typelist<int, char> list;
get<list, 0>::type //returns int
get<list, 1>::type //returns char

Since typelist is a plain list, get<> can be implemented as a constant time random access enumerator.

template<typename T> struct get<T, 0>
{
   enum { index = 0 };
   typedef typename T::type1 type;
};

template<typename T> struct get<T, 1>
{
   enum { index = 1 };
   typedef typename T::type2 type;
};

...

ttl::meta::type_switch

type_switch is a run-time switch-like function on typelists.

struct my_functor
{
   template<typename T>
   void operator()() { ...do something }
};

typedef typelist<int, char> list;
void f()
{
   int type = 0;

   my_functor f;
   type_switch<list> ts;
   ts(type); //calls my_functor::operator()<int>();
   type = 1;
   ts(type); //calls my_functor::operator()<char>();
   type = 2;
   ts(type); //run-time exception
}

ttl::func

func namespace contains:

ttl::func::function

The ttl::func::function is very similar to boost::function (see Sample).

Comments

  1. I was scared by the complexity of the boost::function implementation for such a basic class.

  2. Just including "boost/function.hpp" (10 parameters limit) adds about 4 sec in compilation time on my machine while including "ttl/func/function.hpp" (the same limit) doesn't appear to have any noticeable impact on the compilation time.

ttl::func::named_params_function

named_params_function<> can be used to to convert any function into a functor with named parameters. The declaration consists of pairs (parameter name, parameter type). Here is an example.

#include "ttl/func/named_params_function.hpp"

// there is a C function that is implemented somewhere.
//
int CreateWidget( const char* title, int style );

// define argument names
//
struct title;
struct style;

// declare a function that returns 'int' and accepts
// named paramters 'title' and 'style'
typedef ttl::func::named_params_function<
     int //the function returns 'int'
     (
         //'argument name',  'argument type'

         title,    const char*
        ,style,    numeric_argument<int, 45> //the default is 45
     )
  > create_widget;

int main()
{
     create_widget cw(CreateWidget);

     //call with 'style' 3 and title 'nill'
     cw( cw.arg<style>(3) );

     //call with 'title' "hi" and 'style' 45
     cw( cw.arg<title>("hi") );

     //call with 'title' "hi" and 'style' 5
     //note the order of parameters doesn't matter only names
     cw( cw.arg<style>(5), cw.arg<title>("hi") );

     return 0;
};

create_widget<> can be used with any function or method that have the specified signature. You can find a working sample for class members in samples/test/named_params_test.cpp. The sample used boost::bind for bindind class members.

ttl::var

The var namespace contains

ttl::var::variant

ttl::var::variant has almost the same interface as boost::variant including unary and binary visitors. variant cannot include 'const' types. variant<>::list is the typelist<> class composed of of the variant types.

Comments

There are following differences between ttl variant and boost variant.

    int visitor( my_type& x );

    struct visitor_wrapper
    {
    int return_value;

       void operator()( my_type& x )
       {
          return_value = visitor(x);
       }
    };

    variant<my_type&> var;
    visitor_wrapper vw;
    apply_visitor(var, vw);
    int r = vw.return_value;

We are planning to generalize such a wrapper latter.


ttl::sig

The sig namspace contains:

ttl::sig::signal

tll::sig::signal provides a very similar functionality to boost::signal. Although ttl::sig::signal has a more basic interface comparing to boost::signal, we believe that ttl::sig::signal is a better choice for wide range of applications where the advanced features of boost::signal are not needed. For a sample code, see Sample

Comments
ttl::sig::signal calls connections in the order they created.
Comparison with boost::signal

The following boost::signal features are not supported.

Note: we believe that all these features can be implemented using ttl::sig::signal as a low-level building block.






SourceForge.net Logo