f1
和f2
的演绎是否格式错误?
template<class... T, class U>
void f1(T..., U){}
template<class... T>
void f2(T..., int){}
int main()
{
f1(1);
f2(1);
return 0;
}
g ++接受两者,clang只接受f2
,而msvc拒绝这两者。
相关标准措辞:
当函数参数包出现在非推导的上下文([temp.deduct.type])中时,永远不会推导出该参数包的类型。
未推断的上下文是:
- 不在参数声明列表末尾出现的函数参数包。
所以似乎MSVC在拒绝两者方面都是正确的吗?
这是否意味着即使您明确指定模板args,模板的任何实例化也都会格式不正确?
f1<int>(1, 2); // ill-formed?
f2<int>(1, 2); // ill-formed?
如果是这样的话,为什么要在第一时间允许这样的声明呢?
答案 0 :(得分:2)
此特定问题有DR1388的DR。显然,GCC和CLANG似乎还没有实现它CLANG DR1388。
这是否意味着模板的任何实例化都将是 即使您明确指定模板args,也会形成错误的形式?
$rows = (new \yii\db\Query()) ->select(['*','(SELECT account_name FROM accounts WHERE id = projects.account_id) as account_name']) ->from('projects') ->where(['id' => $id]) ->all();
如果是这样的话,为什么要在第一时间允许这样的声明呢?
否如果您明确指定模板参数,则不会发生扣减,因此上面显示的代码是合法的。
答案 1 :(得分:0)
我自己已经研究过这个问题了,我发现很难得到一个明确的答案。我可以说,f1(1)
应该被拒绝,但f2(1)
应接受。
那说:
正如您所指出的,未在列表末尾出现的函数参数包是非推断的上下文([temp.deduct.type] p5):
未推断的上下文是:
- ...
- 不在参数声明列表末尾出现的函数参数包。
和[temp.deduct.call] p1(通过CWG 1388修改)澄清了这样的参数包从未推断出来。
当函数参数包出现在非推导的上下文中时,永远不会推导出该参数包的类型。
此外,[temp.arg.explicit] p3指定:
尾随模板参数包(14.5.3)没有 否则推断将被推导出一个空的模板参数序列。
所以,考虑到f2(1)
调用:包T是一个尾随的模板参数包(虽然它不是一个尾随的函数参数包),因此它推断为空包并且呼叫有效。
但是,对于f1(1)
,包T也不是尾随模板参数包,因为它后跟U
,因此不会假定每个[temp.arg。显式] p3。因此,由于无法推导出模板参数包T用于f1(1)
的调用,因此它不应参与重载解析,并且调用应该失败。
请注意,在其他讨论中提出了几个类似的问题/示例,但它们都有微妙的不同:
f(0)
调用有效,因为有问题的包是一个尾随模板参数包,因此它属于我上面提到的情况。以下是CWG 1399的代码:
template <class... T> void f(T..., int, T...) { } int main() { f(0); // OK f<int>(0,0,0); // OK f(0,0,0); // error }
目前尚不清楚[标准的当前措辞]是否允许例如:
template<typename... T> void f(typename T::type...) { } int main() { f<>(); }