// 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;
};
}
}