#c
#c
Вопрос:
Я изучаю исходный код loki. ниже MakeTypelist
приведено то, что меня смущает.
class NullType {};
template <class T, class U>
struct Typelist
{
typedef T Head;
typedef U Tail;
};
template
<
typename T1 = NullType, typename T2 = NullType, typename T3 = NullType,
typename T4 = NullType, typename T5 = NullType, typename T6 = NullType,
typename T7 = NullType, typename T8 = NullType, typename T9 = NullType,
typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
>
struct MakeTypelist
{
private:
typedef typename MakeTypelist
<
T2 , T3 , T4 ,
T5 , T6 , T7 ,
T8 , T9 , T10,
T11, T12, T13,
T14, T15, T16,
T17, T18
>
::Result TailResu<
public:
typedef Typelist<T1, TailResult> Resu<
};
template<>
struct MakeTypelist<>
{
typedef NullType Resu<
};
using MyType=MakeTypeList<int, unsigned int, long, unsigned long, float>
Как завершается рекурсивный шаблон?
он не может соответствовать версии пустого типа MakeTypelist
, в конце концов, он будет соответствовать MakeTypelist<NullType, NullType, NullType, NullType .....>
?
Комментарии:
1. Да, я думаю, вы правы, потому
template<> struct MakeTypelist<> ...
что все равно будете использовать аргументы шаблона по умолчанию NullType , так что это эквивалентноtemplate<> struct MakeTypelist<NullType, NullType, ...>
. Однако я не могу найти документацию, подтверждающую это, поэтому я не публикую ответ 🙂2. У Loki есть тест, и код правильный.
3. Обратите внимание, что C 11 и шаблон variadic заменяют
TypeList
.
Ответ №1:
Рекурсивный шаблон завершится из-за template<> struct MakeTypelist<>
определения специализации, которая возвращает NullType
значение Result
.
Эта специализация полностью соответствует следующему варианту кода
template<>
struct MakeTypelist<NullType, NullType, NullType, NullType, ..... /* ... 18 Times ... */>
// .......
Потому что, если не предоставлены все или ни один параметр шаблона, то все непредоставленные параметры шаблона считаются равными значениям по умолчанию, т.Е. = NullType
(См. Определение основного шаблона, в нем есть все 18 аргументов-типов, имеющих значение по умолчанию = NullType
).
Этот выбор аргументов по умолчанию для тех параметров шаблона, которые не предоставлены, имеет ту же логику, что и при использовании функций с аргументами по умолчанию, например, если у вас есть функция like void f(int a = 0, int b = 0)
, вы можете вызвать ее тремя разными способами f()
, f(0)
f(0, 0)
и все они дадут одинаковые результаты. И те аргументы функции, которые не указаны, будут приняты равными значениям по умолчанию. То же самое здесь в специализации шаблона — если вы не предоставляете никаких аргументов, т.е. Не пишете struct MakeTuplelist<>
, то все 18 типов аргументов будут считаться NullType
, потому что все 18 аргументов имеют значения по умолчанию = NullType
, такое же поведение, как в функции с аргументами по умолчанию, приведенными выше. Пример.
Также в специализации вы можете указать только некоторые аргументы шаблона, остальные будут считаться равными значениям по умолчанию, например template<> struct MakeTypelist<int, bool>
, специализация будет полностью совпадать со специализацией template<> struct MakeTypelist<int, bool, NullType, NullType, ...... /* 16 NullTypes */>
.
И рекурсия завершается, потому что самый последний хвост равен MakeTypelist<NullType, NullType, NullType, .....>
, который соответствует специализированной версии MakeTypelist
, которая сокращает рекурсию, предоставляя NullType
значение для Result
.
PS. То же поведение по умолчанию применяется не только к специализации шаблона, но и к использованию, вы можете использовать шаблон как typedef MakeTypelist<> T;
или typedef MakeTypelist<int, bool> T;
в обоих случаях остальные 18 аргументов-типов шаблона станут равными значениям по умолчанию = NullType
.
Комментарии:
1. «template<> struct MakeTypeList<>» равно «template <> struct MakeTypeList<NullType, NullType. ,,,,,>», я не мог понять, есть ли у C правило для этого?
2. @yuandaxing Да, точно, если некоторые аргументы шаблона не указаны, как здесь
struct MakeTypeList<>
, где аргументы не указаны, то аргументы шаблона считаются равными значениям по умолчанию, т.Е. Значениям= NullType
, указанным в определении основного шаблона. Таким образом, в принципе, вы можете либо написать специализацию шаблонаstruct MakeTypeList<NullType, NullType. ,,,,,>
, либоMakeTypeList<>
оба дадут одинаковый результат! Или вы можете просто предоставить 1 или 2 аргумента, подобных этомуstruct MakeTypeList<NullType, NullType>
, остальное берется из значений по умолчанию, а значения по умолчанию= NullType
.3. @yuandaxing Это то же самое, что вызов функции с аргументами по умолчанию, если ваша функция определена как
void f(int a, int b = 12, int c = 34)
, то вы можете вызвать ее какf(8)
илиf(8, 12)
илиf(8, 12, 34)
, и все они будут давать одинаковый результат, если вы предоставляете значения, равные аргументам по умолчанию, те значения, которые не указаны, считаются равными значениям по умолчаниюb
для andc
.4. отличное объяснение
5. @yuandaxing Также вы не ограничены предоставлением ни одного или всех аргументов, вы также можете предоставить только некоторые аргументы, например
template<> struct MakeTypelist<int, bool>
, специализация будет полностью совпадать со специализациейtemplate<> struct MakeTypelist<int, bool, NullType, NullType, ...... /* 16 NullTypes */>