Ответ 1
В вашем коде показаны три новые возможности С++ 11: вариативные шаблоны, пользовательские литералы и статические утверждения.
Общий шаблон вариационного класса указывает ноль или более аргументов, специализированные версии одного или более и ровно один, соответственно.
// digits can be the empty set, so 0 or more arguments
template<char... digits>
struct conv2bin;
// digits can be the empty set, so 1 or more arguments
template<char high, char... digits>
struct conv2bin<high, digits...>
// fully specialized for 1 argument
template<char high>
struct conv2bin<high>
Полный синтаксис вариационных шаблонов немного причудливый, Wikipedia содержит достойную статью. Это особенно полезно для другой функции С++ 11: совершенная переадресация вариационного числа аргументов функции.
Экзотический выглядящий int operator "" _b()
определяет определяемый пользователем литерал, который является способом добавления ваших собственных единиц к вашим типам и выражению. Это просто означает, что целые числа, за которыми следует _b
, помечены определенной "единицей". Дополнительную информацию см. В этом вопросе . Одно практическое преимущество было бы в том, чтобы избежать будущих сбоев приземления на Марсе (где СИ и имперские подразделения были смешаны в их программном обеспечении для посадки, без возможности компилятора его диагностировать).
static_assert
выполняет именно то, что, по вашему мнению, делает: он статически ставит свое состояние, то есть в время компиляции. Когда утверждение не выполняется, компиляция прекращается. Это отличный способ обнаружить ошибки как можно скорее.
UPDATE
Специализация вариационных шаблонов может быть очень удивительной, если у вас есть частично перекрывающиеся диапазоны аргументов: версия с нулевыми или более аргументами будет соответствовать только пустым спискам в вашем примере (в случае, если вы предоставили определение для него).
#include <iostream>
template<int... Args>
struct Test
{
enum { value = 0 };
};
template<int I, int... Args>
struct Test<I, Args...>
{
enum { value = 2 };
};
template<int I>
struct Test<I>
{
enum { value = 1 };
};
int main()
{
std::cout << Test<>::value << "\n"; // matches zero or more version
std::cout << Test<0>::value << "\n"; // matches single argument version
std::cout << Test<0, 0>::value << "\n"; // matches one or more version, not the zero or more one!
}
Вывод на LiveWorkSpace.
Это, конечно, пример общего правила для частичной специализированности шаблонов, в котором указано, что будет выбрана самая специализированная версия (один или более более специализированный, чем нуль или более, так как последнее всегда можно использовать там, где первое может, но не наоборот). Но поскольку вариативные шаблоны часто не так "заметно" отличаются друг от друга, вы должны быть осторожны с их частичными специализациями.