Я задавался вопросом, обеспечивает ли C++ 0x какие-либо встроенные возможности проверить, содержит ли пакет параметра шаблона variadic определенный тип. Сегодня, повысьте::: mpl:: содержит может использоваться для выполнения этого, если Вы используете повышение:: mpl:: вектор вместо надлежащих шаблонов variadic. Однако это имеет серьезное время компиляции наверху. Я предполагаю, C++ 0x имеет поддержку уровня компилятора станд.:: is_same. Таким образом, я думал, поддерживается ли обобщение как ниже также в компиляторе.
template <typename... Args, typename What>
struct is_present
{
enum { value = (What in Args...)? 1 : 0 };
};
Нет, вы должны использовать (частичную) специализацию с вариационными шаблонами, чтобы делать вычисления времени компиляции, такие как это:
#include <type_traits>
template < typename Tp, typename... List >
struct contains : std::true_type {};
template < typename Tp, typename Head, typename... Rest >
struct contains<Tp, Head, Rest...>
: std::conditional< std::is_same<Tp, Head>::value,
std::true_type,
contains<Tp, Rest...>
>::type {};
template < typename Tp >
struct contains<Tp> : std::false_type {};
Существует только одна другая внутренняя операция для вариационных шаблонов, и это специальное Форма оператора Sazeof, который вычисляет длину списка параметров, например:
template < typename... Types >
struct typelist_len
{
const static size_t value = sizeof...(Types);
};
, где вы получаете «У него есть серьезные компиляционные накладные расходы» с Boost MPL от? Я надеюсь, что вы не просто делаете предположения здесь. Boost MPL использует такие методы, как ленивый шаблон, чтобы попытаться уменьшить время компиляции, а не взорванию, как наивный шаблон Meta-программирование.
Если вы хотите избежать рекурсиона ручного типа, STD :: Common_Type
, по-видимому, является единственной утилитой в STL, который является вариационным шаблоном, и Следовательно, единственный, который мог бы потенциально инкапсулировать рекурсию.
STD :: Common_Type
находит наименее полученный тип в наборе типов. Если мы определим числа с типами, специально высокими числами с менее полученными типами, он находит наибольшее количество в наборе. Затем мы должны сопоставить равенство к ключевому типу на уровень вывода.
using namespace std;
struct base_one { enum { value = 1 }; };
struct derived_zero : base_one { enum { value = 0 }; };
template< typename A, typename B >
struct type_equal {
typedef derived_zero type;
};
template< typename A >
struct type_equal< A, A > {
typedef base_one type;
};
template< typename Key, typename ... Types >
struct pack_any {
enum { value =
common_type< typename type_equal< Key, Types >::type ... >::type::value };
};
Мы можем взломать common_type
немного больше. Стандарт говорит
Программа может специализироваться на этой черте, если по крайней мере один параметр шаблона в Специализация - это пользовательский тип.
И описывает именно то, что находится внутри: рекурсивный случай частичной специализации, случай, который применяет двоичный оператор и терминал. По сути, это общий Fold
функция , и вы можете добавить любой двоичной операции, которую вы будете. Здесь я использовал дополнение, потому что это более информативно, чем. Обратите внимание, что IS_Same
возвращает Integral_Constant
.
template< typename Addend >
struct type_sum { // need to define a dummy type to turn common_type into a sum
typedef Addend type;
};
namespace std { // allowed to specialize this particular template
template< typename LHS, typename RHS >
struct common_type< type_sum< LHS >, type_sum< RHS > > {
typedef type_sum< integral_constant< int,
LHS::type::value + RHS::type::value > > type; // <= addition here
};
}
template< typename Key, typename ... Types >
struct pack_count : integral_constant< int,
common_type< type_sum< is_same< Key, Types > > ... >::type::type::value > {};