4

У меня есть этот кусок кода и хочу, чтобы понять:Понять, как вычислить сумму во время компиляции

template <unsigned...> 
struct sum; 

template<unsigned size> 
struct sum<size> 
{ 
    enum {value = size}; 
}; 

template<unsigned size, unsigned... sizes> 
struct sum<size, sizes...> 
{ 
    enum { value = size + sum<sizes...>::value }; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    sum<1, 2>::value; 
    return 0; 
} 

Я не понимаю, почему невыполненная сумма (которая принимает беззнаковую ... так же, как последний STRUCT специализацию , не конфликт?) должен присутствовать на всех и как можно специализироваться сумму, используя те же параметры из шаблона части (e.g. sum<size, sizes...> же, как template <unsigned size, sizes...>. Почему ниже просто не работает?

template<unsigned size> 
struct sum 
{ 
    enum {value = size}; 
}; 

template<unsigned size, unsigned... sizes> 
struct sum 
{ 
    enum { value = size + sum<sizes...>::value; }; 
}; 

ответ

7

Примечание что синтаксис немного отличается. При объявлении основного шаблона:

template <unsigned...> 
struct sum; 

Вы не даете параметры шаблона после sum. Это связано с тем, что вы создаете совершенно новый шаблон и говорите, что он принимает произвольное количество целых чисел без знака в качестве параметров.

Когда вы делаете это:

template<unsigned size, unsigned... sizes> 
struct sum<size, sizes...> 
{ 
    enum { value = size + sum<sizes...>::value }; 
}; 

вы Специализируя шаблон, который вы объявленную ранее. Вы говорите, что в случае, когда ваши параметры состоят из значения без знака, за которым следует произвольное количество других значений без знака, используйте это определение. Это не совсем то же самое, что и основной шаблон. Основной шаблон включает возможность наличия нулевых параметров.

При попытке сделать это:

template<unsigned size> 
struct sum 
{ 
    enum { value = size }; 
}; 

template<unsigned size, unsigned... sizes> 
struct sum // OOPS! A template called `sum` has already been declared! 
{ 
    enum { value = size + sum<sizes...>::value }; 
}; 

вы пытаетесь сделать два различных шаблонов класса с тем же именем, что не допускается.

Обратите внимание, что это немного отличается от того, как работают шаблоны функций. С помощью шаблонов функций вы можете выполнять перегрузку, поэтому наличие нескольких шаблонов функций с тем же именем в порядке. Однако с помощью шаблонов функций вы не можете выполнять частичную специализацию, так как это создаст много двусмысленности.

Возможно, вы считаете, что между основным шаблоном и специализациями существует двусмысленность, но более специализированные специализации всегда имеют приоритет перед менее специализированными специализациями, а первичный шаблон всегда можно считать наименее специализированным. Если это не так, то частичная специализация не будет работать вообще.

+0

Да, я понимаю, что касается именования. Но как получается, что первая нереализованная сумма не затухает (неоднозначна) с последней? Когда пользователь называет сумму <1, 2>, она должна соответствовать как нереализованной, так и последней специализации – Gmt

+1

@Gmt: Это правда, но специализации имеют приоритет. Я добавил к этому сообщение об этом. –

0

Первое объявление:

template<unsigned int... Ns> 
struct sum; 

является опережающим объявлением: Он объявляет шаблон как шаблон с переменным числом параметров unsigned int.

Первая специализацией является базовым случаем metafunction, который содержит тот случай, когда VARIADIC пакета имеет только один параметр:

template<unsigned size> 
struct sum<size> 
{ 
    enum {value = size}; 
}; 

вторая специализацией является рекурсивным случаем: Это имеет место случая, когда VARIADIC-пакет имеет, по меньшей мере, один параметр:

template<unsigned size, unsigned... sizes> 
struct sum<size, sizes...> 
{ 
    enum { value = size + sum<sizes...>::value }; 
}; 

Я предлагаю вам узнать больше о механизмах шаблонов C++ (например, instantation, специализации шаблона и т.д.) перед писать/изучать шаблонный мета-программирования.

+1

A * forward declaration * - это просто * объявление *. Ничего особенного в этом, поэтому зачем это подчеркивать? В любом случае * подчеркивайте * это ** первичный * шаблонный шаблон * декларация **. – Nawaz

+0

@Nawaz Я пытаюсь усилить то, что декларация вперед может рассматриваться как * объявление * метафакса, а специализации - случаи рекурсивного метафунта. – Manu343726

Смежные вопросы