将C数组传递给类作用域内声明的静态函数

5
为什么在以下示例中,如果静态函数在类作用域内声明,编译器会无法绑定同一静态函数?
#include <vector>
#include <iostream>

struct Foo
{
static constexpr int GetSize()
{
    return 5;
}
static void ProcessArrayWrong(int(&indices)[Foo::GetSize()])
{
    for(int i =0; i < Foo::GetSize(); i++)
    {
        indices[i]++;
    }
}
};

static void ProcessArray(int(&indices)[Foo::GetSize()])
{
    for(int i =0; i < Foo::GetSize(); i++)
    {
        indices[i]++;
    }
}

int main(int argc, char* argv[])
{
    int foo[Foo::GetSize()] = {1,2,3,4,5};

    for(int i =0; i < Foo::GetSize(); i++)
    {
        std::cout << foo[i]++ << std::endl; 
    }
    ProcessArray(foo);
    ProcessArrayWrong(foo); // fails here
    for(int i =0; i < Foo::GetSize(); i++)
    {
        std::cout << foo[i]++ << std::endl; 
    }
    return 0;
}

错误信息为:

错误:非常量左值引用不能绑定到无关类型值 'int'。


在评论中提供的问题似乎解释了为什么会出现这个错误。感谢。 现在我们需要知道以下问题和链接文章中提供的答案有关:
  1. 为什么“模板技巧”能起作用?我猜是因为模板代码需要额外的编译步骤,但我更想得到一个更清晰的意见。
  2. 声明函数为模板是否会导致任何非期望的行为或是安全使用的?

2
可能是这个:https://dev59.com/-mQn5IYBdhLWcg3w5aay#16493853 - Stephen Newell
谢谢 @Stephen Newell: 我认为你是正确的。 - Heisenbug
“模板技巧”是必需的,因为int(&indices)[Foo::GetSize()]是一个不完整的类型,在编译时引用了一个“谁知道有多大”的数组。 - David C. Rankin
谢谢,我明白了。使用它是安全的吗?还是有什么不明显的缺点? - Heisenbug
1个回答

1
“模板技巧”之所以有效,是因为模板(和类模板的成员函数)已经按需实例化。虽然标准实际上并没有说这个属性允许在诸如数组大小之类的东西中使用成员函数,但非模板情况下也没有任何实际规则反对它,常见的实现策略支持这个技巧作为一个副产品。
鉴于当前观点认为(类)模板行为更正确,依靠它可能是安全的。此外,标准库将各种事物隐式地声明为模板,表明它通常不会引起问题。(您甚至可以使用显式实例化来将函数模板的定义放在其他地方。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接