我在C++ 11中从未见过的代码

Pau*_*aul 15 c++ static-assert user-defined-literals variadic-templates c++11

我在看这个源代码

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];
Run Code Online (Sandbox Code Playgroud)

我想知道这是否是有效的C++.

template<char high, char... digits>
struct conv2bin<high, digits...> {
Run Code Online (Sandbox Code Playgroud)

这是什么?不专门的模板专业化?

为什么结构声明里面有代码行呢

struct conv2bin<high> {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0');
};
Run Code Online (Sandbox Code Playgroud)

我糊涂了..

Tem*_*Rex 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>
Run Code Online (Sandbox Code Playgroud)

可变参数模板的完整语法有点古怪,维基百科上有一篇不错的文章.它对于另一个C++ 11特性特别有用:完美转发可变数量的函数参数.

异国情调的外观int operator "" _b()定义了用户定义的文字,这是一种将自己的单位添加到类型和表达式的方法.它只是意味着后面的整数_b被标记为某个"单位".有关详细信息,请参阅此问题.一个实际的好处是避免未来的火星着陆器崩溃(其中SI和英制单位在其着陆软件中混合,而编译器无法对其进行诊断).

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!
}
Run Code Online (Sandbox Code Playgroud)

LiveWorkSpace上的输出.

这当然是部分模板特化的一般规则的一个例子,它表明将选择最专业的版本(一个或多个比零或更多更专业,因为后者总是可以在前者使用的地方使用可以,但反之亦然).但由于可变参数模板通常不会彼此"明显地"不同,因此您应该特别注意它们的部分特化.