首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我在C++11中从未见过的代码

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

Stack Overflow用户
提问于 2013-04-15 17:46:22
回答 2查看 1.2K关注 0票数 15

我在看这个源代码

代码语言:javascript
运行
复制
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++。

代码语言:javascript
运行
复制
template<char high, char... digits>
struct conv2bin<high, digits...> {

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

以及为什么struct声明中有代码行,例如

代码语言:javascript
运行
复制
struct conv2bin<high> {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0');
};

我很困惑..。

EN

回答 2

Stack Overflow用户

发布于 2013-04-15 17:47:53

您的代码展示了三个新的C++11特性:可变模板用户定义的文字静态断言

一般的变量类模板指定零或多个参数,专门的版本分别指定一个或多个参数,准确地指定一个参数。

代码语言:javascript
运行
复制
// 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>

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

异国情调的int operator "" _b()定义了用户定义的文字,这是一种将自己的单元添加到类型和表达式中的方法。它简单地意味着整数后面跟着_b是用一个特定的“单位”标记的。有关更多细节,请参见此问题。一个实际的好处是避免未来火星着陆器坠毁(在那里SI和帝国单位被混合在他们的着陆软件中,而编译器不能诊断它)。

static_assert完全按照您的想法来做:它静态地断言它的条件,即在static_assert上。当断言失败时,编译将停止。这是尽快检测错误的好方法。

更新

当您有部分重叠的参数范围()时,变量模板的专门化可能非常令人惊讶:零或多个参数版本将只匹配示例中的空列表(万一您已经为它提供了定义)。

代码语言:javascript
运行
复制
#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上输出。

这当然是部分模板专门化的一般规则的一个例子,该规则规定将选择最专门化的版本(一个或多个版本比零或更多,因为后者总是可以在前者可以使用的地方使用,反之亦然)。但是,由于各种模板之间通常并不是“明显的”不同,所以您应该特别注意它们的部分专门化。

票数 22
EN

Stack Overflow用户

发布于 2013-04-15 18:12:26

代码语言:javascript
运行
复制
template<char... digits>
struct conv2bin;

这是一个模板转发声明。不必完全定义它,因为如果以不受支持的方式使用它,您将很快捕获错误(编译将失败)。这个特殊的例子不会导致编译失败,因为专门化涵盖了所有可能的情况。

代码语言:javascript
运行
复制
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成员变量,它的值取决于'high‘值和下一个模板。

代码语言:javascript
运行
复制
template<char high>
struct conv2bin<high> {
    static_assert(high == '0' || high == '1', "no bin num!");
    static int const value = (high - '0');
};

同样,部分模板专门化,在模板参数仅包含其列表中的一个参数时定义值。

因此,总的来说,这是一个使用各种模板的模板元编程

静态断言的存在是为了限制模板变量可以接受的值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16021509

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档