ПРИМЕЧАНИЕ: Я полагал, что специализация шаблонов не является решением, потому что класс намного больше, чем в коде, который вы нам предоставляете (поскольку вы сосредоточили свой вопрос на проблеме, молодцы). Все здесь ненавидят вопросы с тысячами строк кода и вопрос вроде: «Что случилось?»)
У вас есть доступ к C++ 11? Если ответ да, то не использовать списки типов лков стиля, использовать более простые списки типов VARIADIC-шаблоны на основе:
template<typename... Ts>
struct TypeList{};
Реализации TypeList операции слишком просто.
Даже если вы используете списки типов локи стиле или VARIADIC списки типов шаблонов, решение для вашей проблемы точно так же: enable_if
template<bool CONDITION , typename T>
struct enable_if;
template<typename T>
struct enable_if<true,T> { typedef type T; };
template<typename T>
struct enable_if<false,T> {};
Как вы, вероятно, заметили, ложный specialitation не определен ЬурейеЕ type
из тип T. Это означает, что если вы используете enable_if
в двух местах, где условие истинно и где условие ложно, будет создано только одно из мест. Зачем? Потому что вы используете член type
в обоих, но в фальшивом случае его не определено.
Смотрите пример: (Supose мы имеем metafunction is_floating_point
, которая проверяет, является ли данный тип является типом с плавающей точкой)
template<typename T>
typename enable_if<is_floating_point<T>::value , bool> are_equal(const T& a , const T& b)
{
const T epsilon = 0.0001;
return std::abs(a-b) < epsilon;
}
template<typename T>
typename enable_if<!is_floating_point<T>::value , bool> are_equal(const T& a , const T& b)
{
return a == b;
}
В этом примере enable_if
используется условно генерировать версию с плавающей точкой функция сравнения.
Но в вашем случае есть проблема. Правильная реализация функции шаблона может зависеть только от собственных аргументов, как в примере (зависит от T
, который является параметром функции).
Но это не ваш случай: представление одного параметра перегрузки foo_private
и foo_public
не зависит от функциональных параметров, зависит от классового требования (список типов).
В C++ 11 вы можете решить эту проблему написания функции как функции шаблона, и проходящее состояние не-функции (размер TypeList в нашем случае) в качестве значения по умолчанию шаблона:
template<unsigned int size_of_list = SizeOf<TypeList>::value>
typename enable_if<size_of_list > 1 , void>::type foo_public (const TypeAt<TList, 0>& t0, const TypeAt<TList, 1>&t1)
{
foo_private(t0, t1)
}
template<unsigned int size_of_list = SizeOf<TypeList>::value>
typename enable_if<size_of_list > 1 , void>::type foo_private (const TypeAt<TList, 0>& t0, const TypeAt<TList, 1>&t1)
{
/*do stuff with t1*/
foo_private(t0);
}
Если у вас нет доступа к чему-либо из C++ 11, вы можете попробовать другой способ.Предположим, у нас есть условный селектор типа:
template<bool CONDITION , typename T , typename U>
struct conditional;
template<typename T , typename U>
struct conditional<true,T,U> { typedef type T; };
template<typename T , typename U>
struct conditional<false,T,U> { typedef type U; };
Другой способ решения ваших перегруженных является использование unmeanning типа (Innaccesible пользователем) в том случае, когда TypeList содержит только один тип:
template<typename TList/*TList - Alexandrescu's typelist*/>
class TheClass
{
class UnmeanningType {}; //This type must be private
typedef typename conditional<SizeOf<TList>::value > 1 , TypeAt<TList , 1> , UnmeanningType>::type SecondArgType;
void foo_public (const TypeAt<TList, 0>& t0, const SecondArgType& t1)
{
foo_private(t0, t1)
}
void foo_private (const TypeAt<TList, 0>& t0, const SecondArgType& t1)
{
/*do stuff with t1*/
foo_private(t0);
}
void foo_public (const TypeAt<TList, 0>& t0)
{
foo_private(t0);
}
void foo_private(const TypeAt<TList, 0>& t0)
{
/*do stuff with t0*/
}
};
При таком подходе, если список типов содержит только один тип, перегрузка двух аргументов использует UnMeanningType в качестве типа seccond arg, который пользователь (теоретически) не знает. Таким образом, теоретически, пользователь может использовать только одну переменную arg в этом случае.
Что вы пытаетесь достичь? – Nawaz
@Nawaz: Я хочу создать сериализатор шаблонов. Присвойте шаблон шаблону, например 'serializator>', а затем 'serialize (10,12, reference_to_some_class_object)' –
fogbit