被这种语法弄糊涂了
Puzzled by this syntax
当我在cppreference.com上阅读关于SFINAE的文章时,我遇到了一个我无法理解的片段:
template <int I> void div(char(*)[I % 2 == 0] = 0)
到底是什么
char(*)[I % 2 == 0] = 0
它看起来像是一个指向返回char的函数的指针,但带bool的方括号是什么?它是真的吗?还是只是一些愚蠢的人造例子?
您看到的是旧时尚风格的SFINAE。
背景:SFINAE:替换失败不是错误
当您尝试实例化一个模板时,它会检查该模板是否可以在没有错误的情况下实例化。如果发生错误,则根本不会发生任何事情,当前尝试的模板将被忽略。通常,您有两个或多个模板定义,但一次只能实例化一个模板定义而不会出现错误。
在您的情况下,将创建一个数组,如果我是偶数,则结果是大小为零的数组。这是一个编译错误,但用作模板声明时,它会失败并被忽略。因此,您可以使用这样的语句来选择将根据参数实例化哪个模板。
详细语法:
template <int I> void div(char(*)[I % 2 == 0] = 0)
我们有一个模板,采用一个参数:int I。然后,模板定义了一个函数,该函数将指针指向一个大小为"I%2==0"的char数组,这将导致逻辑从bool到int的转换。因此,如果我是偶数,则结果为零->SFINAE将失败,实例被忽略,如果我为奇数,则得到true->转换为1。这意味着,创建一个指向大小为1的字符指针数组的指针。好的,将创建实例。在有了指针之后,它将默认初始化为0。
在这里,我们看到偶数或奇数I可以用来选择两个(或多个(模板中的哪一个将被实例化。
在更"现代"的C++中,我们看到std::enable_if来选择要实例化的模板。这使其可读性更强。但是在c++11之前,c++没有这个。因此,为SFINAE生成错误的需要通常是通过创建负或零大小的数组来完成的。这是老式代码中常见的SFINAE破解方法。
如果将参数名称放入:中,可能会变得更清楚
void div(char (*x)[I % 2 == 0] = 0)
x
是指向大小为1
(表示true(或0
(表示false(的数组的指针,默认为nullptr
。
但是参数名称在C++中是可选的,所以如果函数不使用x
,它可以省略名称。
char(*)[I % 2 == 0] = 0
是大小为1的字符数组上的指针(当I为偶数时(和0(当我为奇数时(,指针默认为0
因为您不能创建大小等于0的数组,所以只有当我是时才能调用此重载
- 1d 智能指针不适用于语法 (*)++
- 助记符和指向成员语法的指针
- 有人能分解一下这个c++模板的语法吗
- C++避免重复声明的语法是什么
- QMetaObject invokeMethod的基于函数指针的语法
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 当我尝试添加 2 个大字符串时,我无法弄清楚出了什么问题
- 单独定义模板化嵌套类方法的正确语法
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 被这种语法弄糊涂了
- 无法弄清楚将多个对象函数作为单独的线程调用的语法
- 被所有关于向ec2linux添加新glib版本的帖子弄糊涂了
- 被管道弄糊涂了。"cat -A"似乎过滤掉了部分输出
- 被这个汇编代码弄糊涂了
- 被lambda输出弄糊涂了
- 我无法弄清楚C++语法错误"expected `;' before ‘{’ token"
- 被增强精灵/凤凰/ c++ 11的交互弄糊涂了
- 被gprof输出弄糊涂了——调用太多
- 把自己弄糊涂了,指针对指针太多了