对此语法感到困惑

时间:2018-07-16 07:16:17

标签: c++ function

当我在cppreference.com上阅读有关SFINAE的信息时,遇到了我无法理解的代码片段:

    template <int I> void div(char(*)[I % 2 == 0] = 0) 

那到底是什么

    char(*)[I % 2 == 0] = 0

它看起来像是一个指向返回char的函数的指针,但是里面有一个布尔值的方括号是什么。它是真实的东西还是仅仅是一些愚蠢的人工例子?

3 个答案:

答案 0 :(得分:4)

您看到的是SFINAE中的旧时尚。

背景: SFINAE:替换失败不是错误

当您尝试实例化模板时,它将检查模板是否可以实例化而没有错误。如果发生错误,则什么也不会发生,当前尝试的模板将被忽略。通常,您有两个或多个模板定义,但是一次只能实例化一个而不会出错。

在您的情况下,将创建一个数组,如果我是偶数,则结果是大小为零的数组。这是一个编译错误,但是用作模板声明时,它会失败并被忽略。这样,您可以使用这样的语句来选择要根据参数实例化的模板。

详细语法:

template <int I> void div(char(*)[I % 2 == 0] = 0)

我们有一个模板,带有一个参数:intI。 然后,模板定义了一个函数,该函数使用一个指向大小为“ I%2 == 0”的char数组的指针,这导致逻辑上的布尔值向int值的转换。这样,如果我为偶数,则结果为零-> SFINAE将失败,实例被忽略,如果我为奇数,则为true->转换为1。这意味着,您将创建一个指向大小为1的char指针数组的指针OK,实例将被创建。有了指针后,它将默认初始化为0。

在这里,我们可以使用偶数或奇数I来选择要实例化两个(或更多)模板中的哪个。

在更多的“现代” C ++中,我们看到std :: enable_if选择要实例化的模板。这使其更具可读性。但是在c ++ 11之前,c ++没有。因此,通常需要通过创建负数或零大小的数组来为SFINAE生成错误。对于SFINAE来说,这是旧式代码中的常见技巧。

答案 1 :(得分:3)

如果将参数名称输入:

void div(char (*x)[I % 2 == 0] = 0)

x是指向大小为1(代表真)或0(代表假)的数组的指针,默认为nullptr

但是参数名称在C ++中是可选的,因此,如果函数不使用x,则可以忽略该名称。

答案 2 :(得分:2)

char(*)[I % 2 == 0] = 0是一个在大小为1的char数组上的指针,当我为偶数时为0,当我为奇数时为0,并且该指针默认为0

因为您无法创建大小等于0的数组,所以这种重载只能在我偶数时调用

相关问题