temp. deduction .type#17指定
如果在带有非类型模板形参的函数模板声明中,该非类型模板形参用于函数形参列表中的子表达式中,则该表达式是如上所述的非推导上下文。
表示对于下面的f
template<int> struct S {};
template<int i> void f(S<i + 1>) {}
呼叫f(S<42>{})
被拒绝。
但是,如果将f
的声明更改为
template<int i> void f(S<(i)>) {}
只有Clang拒绝调用,错误和之前一样。
那么,在i
周围添加括号是否使其成为非推导上下文,因为i
是(i)
的子表达式?
子表达式是相对于直接子表达式定义的:
表达式E的子表达式是E的直接子表达式或E的直接子表达式的子表达式
和直接子表达式部分定义为:
表达式E的直接子表达式为
- E的操作数组成表达式([exp .prop]),
有更多的可能性,但它们显然不适用于(N)
的情况。所以问题是N
是否是括号表达式的操作数。
根据[exp .prim.paren]/1:
带括号的表达式(E)是一个主表达式,其类型、值和值类别与E的类型、值和值类别完全相同。除了另有说明外,带括号的表达式可以用于与E完全相同的上下文中,并且具有相同的含义。
重点补充道。显然,(N)
N
不是一个操作数,所以它不是一个直接的子表达式,因此N
不是子表达式。
由于[temp. deduction .type]/17中没有任何"另有指示"的内容,很明显(N)
和N
可以被相同地使用。