我正在查看此源代码
template<char... digits>
struct conv2bin;
template<char high, char... digits>
struct conv2bin<high, digits...> {
static_assert(high == '0' || high == '1', "no bin num!");
static int const value = (high - '0') * (1 << sizeof...(digits)) +
conv2bin<digits...>::value;
};
template<char high>
struct conv2bin<high> {
static_assert(high == '0' || high == '1', "no bin num!");
static int const value = (high - '0');
};
template<char... digits>
constexpr int operator "" _b() {
return conv2bin<digits...>::value;
}
int array[1010_b];
我想知道这是否是有效的C ++。
template<char high, char... digits>
struct conv2bin<high, digits...> {
这是什么?一个不专门的模板专业化?
为什么结构声明里面有代码行,比如
struct conv2bin<high> {
static_assert(high == '0' || high == '1', "no bin num!");
static int const value = (high - '0');
};
我很困惑..
答案 0 :(得分:22)
您的代码显示了三个新的C ++ 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上有一篇不错的文章。它对于另一个C ++ 11特性特别有用:完全转发的可变数量的函数参数。
异国情调的int operator "" _b()
定义了用户定义的文字,这是一种将自己的单位添加到类型和表达式的方法。它只是意味着_b
后跟的整数被标记为某个“单位”。有关详细信息,请参阅此question。一个实际的好处是避免未来的火星着陆器崩溃(其中SI和英制单位在其着陆软件中混合,而编译器无法对其进行诊断)。
static_assert
完全符合你的想法:它静态地断言它的条件,即在编译时。断言失败时,编译停止。这是一种尽快检测错误的好方法。
<强>更新强>
当你有部分重叠的参数范围时,可变参数模板的专业化会非常令人惊讶:零或多个参数版本只会匹配示例中的空列表(如果你提供了一个它的定义)。
#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上的输出。
这当然是部分模板专业化的一般规则的一个例子,它表明将选择最专业的版本(一个或多个比零或更多更专业,因为后者总是可以在前者可以使用的地方使用,但反之亦然。但由于可变参数模板通常不会彼此“明显地”不同,因此您应该特别注意它们的部分特化。
答案 1 :(得分:1)
template<char... digits>
struct conv2bin;
这是模板转发声明。它不必完全定义,因为如果以不支持的方式使用它,您将更快地捕获错误(编译将失败)。这个特殊的例子不会导致编译失败,因为专业化涵盖了所有可能的情况。
template<char high, char... digits>
struct conv2bin<high, digits...> {
static_assert(high == '0' || high == '1', "no bin num!");
static int const value = (high - '0') * (1 << sizeof...(digits)) +
conv2bin<digits...>::value;
};
这是部分特化,其中设置了一个模板值。其余的只是转发到模板类型的“较低层级”。此模板结构已完全定义,并包含一个int成员变量,该值取决于“高”值和下一个模板。
template<char high>
struct conv2bin<high> {
static_assert(high == '0' || high == '1', "no bin num!");
static int const value = (high - '0');
};
再次部分模板专门化,定义模板参数在其列表中只包含一个参数时的值。
所以,总的来说,这是使用可变参数模板的template meta-programming。
静态断言用于限制模板变量可以采用的值。