为什么C++不能推断带有偏移量的数组大小?

6

这段代码无法编译

template<unsigned n>
void test(char const (*)[n + 1]) { }

int main()
{
    char const arr[] = "Hi";
    test(&arr);
}

出现错误

note: candidate template ignored: couldn't infer template argument 'n'

然而,如果您将n+1更改为n,它会编译通过。

为什么编译器不能推断出在其上加了偏移量的n


但是你究竟想要实现什么,我不太明白?我的意思是,兼容类型的规则要求数组维度一一匹配。 - AnArrayOfFunctions
6
做个头脑锻炼怎么样?如果将模板指定为void test(char const (*)[(n+3)*(n-2)]),当传入一个由84个字符组成的数组时,你是否期望C++编译器将n推断为9? - Sam Varshavchik
@SamVarshavchik:不,但这并不意味着它不能处理基本的仿射表达式。 - user541686
1个回答

8

来自cppreference,在“非推导上下文”一章中:

下面情况中用于组成P的类型、模板和非类型值不参与模板参数推导,而是使用在其他地方被推导或显式指定的模板参数。如果一个模板参数仅在非推导上下文中使用且没有被显式指定,则模板参数推导失败。

(...)

  1. 非类型模板参数或数组维数中包含子表达式引用了模板参数:
template<std::size_t N> void f(std::array<int, 2 * N> a);
std::array<int, 10> a;
f(a); // P = std::array<int, 2 * N>, A = std::array<int, 10>:
      // 2 * N is non-deduced context, N cannot be deduced
      // note: f(std::array<int, N> a) would be able to deduce N 

(...)

总之,如果类型名称的任何一部分都无法推导,则整个类型名称都是无法推导的上下文。 (...)

由于 n + 1 是一个子表达式,因此整个上下文都不能被推导。


+1 谢谢。但是你知道 (n) 应该可以工作吗?因为它在 Clang 上失败了,但在 GCC 和 MSVC 上可以工作。 - user541686
@user541686 我认为Clang是正确的。(n)应该使n成为子表达式,这应该使整个表达式成为一个非推断上下文。这也是Clang的错误消息所说的“无法推断模板参数...”。 - cigien

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