Click here to Skip to main content
15,885,886 members
Articles / Programming Languages / VC++

Static Value Lists

Rate me:
Please Sign up or sign in to vote.
4.60/5 (7 votes)
25 Aug 2011CPOL18 min read 23.5K   246   17  
An introduction to advanced template metaprogramming using an explanatory project
// This file is part of the lobster library
// Copyright: Andreas Raczek
// This file is published under the The Code Project Open License (CPOL) 
// See the file "CPOL.html" for the full license governing this code. 
#pragma once

namespace lobster {

namespace static_list {

// An item is inserted into a static list at a given item index 
// (The item at that index will be appended). If the index is 0, the 
// new list item will be the first item in the list. If the index
// is not present in the list, the new item will be appended at 
// the end of the list.
// 
// Calling form for adding a single enumerator to the list:
// list_insert_at<BaseList, idx, value>::type
//
// Calling form for adding an enumerator range to the list:
// list_insert_at<BaseList, idx, value_first, value_last>::type

// Implementation:
// list_insert_at<...> checks if the insertion position is reached
// and calls list_insert_at_switch<...> with the result (index_pos type)
// as parameter. For each index_pos value, there is one list_insert_at_switch<...>
// specialization:
//
// list_insert_at_switch<..., index_in_range> 
// The insertion position has not yet been reached.
// Calls list_insert_at<...> on its parent,
// then wrap with current list item.
// 
// list_insert_at_switch<..., index_equals>:
// The insertion postion has been reached.
// At insert pos, append new list item,
// then wrap with current list item.
//
// list_insert_at_switch<..., index_out_of_range>
// The insertion pos is not valid, append
// at the end of the list.

// This enumeration is used as parameter
// to list_insert_at_switch in order to select
// the correct specialization
enum index_pos {
    index_equals,         //< the list<...> where the new enumerator is to be inserted before is found
    index_in_range,       //< the requested index lies in the list<...> range
    index_out_of_range    //< the requested index does not exist in the list<...> range
};


template<
    typename list_item, 
    int idx,
    typename list_item::value_type new_value_first,
    typename list_item::value_type new_value_last = new_value_first
> struct list_insert_at;


template<
    typename list_item, 
    typename list_item::value_type new_value_first,
    typename list_item::value_type new_value_last,
    int idx,
    index_pos index_tag
> struct list_insert_at_switch;


#pragma region "list_insert_at_switch<..., index_in_range>" 

template<
    typename parent_list,
    typename parent_list::value_type parent_value_first,
    typename parent_list::value_type parent_value_last,
    typename parent_list::value_type new_value_first,
    typename parent_list::value_type new_value_last,
    int idx
> struct list_insert_at_switch<
    list_item<parent_list, parent_value_first, parent_value_last>,
    new_value_first,
    new_value_last,
    idx,
    index_in_range
> {
    typedef list_item<
        typename list_insert_at<parent_list, idx, new_value_first, new_value_last>::type, 
        parent_value_first,
        parent_value_last
    > type;
};

#pragma endregion


#pragma region "list_insert_at_switch<..., index_equals>"

template<
    typename parent_list,
    typename parent_list::value_type parent_value_first,
    typename parent_list::value_type parent_value_last,
    typename parent_list::value_type new_value_first,
    typename parent_list::value_type new_value_last,
    int idx
> struct list_insert_at_switch<
    list_item<parent_list, parent_value_first, parent_value_last>,
    new_value_first,
    new_value_last,
    idx,
    index_equals
> {
    typedef list_item<
        list_item<parent_list, new_value_first, new_value_last>, 
        parent_value_first,
        parent_value_last
    > type;
};

#pragma endregion 


#pragma region "list_insert_at_switch<..., index_out_of_range>"

template<
    typename list,
    typename list::value_type new_value_first,
    typename list::value_type new_value_last,
    int idx
> struct list_insert_at_switch<
    list,
    new_value_first,
    new_value_last,
    idx,
    index_out_of_range
> {
    typedef list_item<
        list, 
        new_value_first,
        new_value_last
    > type;
};

#pragma endregion


template<
    typename list,
    int idx,
    typename list::value_type new_value_first,
    typename list::value_type new_value_last
> struct list_insert_at 
{
    const static index_pos ip = 
        idx == list::size - 1 ? index_equals :
        idx >= list::size ? index_out_of_range :
        idx < 0 ? index_out_of_range :
        index_in_range;
        
    typedef typename list_insert_at_switch<
        list, 
        new_value_first, 
        new_value_last,
        idx, 
        ip
    >::type type;
};


}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions