Bar*_*rry 10 c++ gcc templates clang language-lawyer
考虑以下设计的代码:
template <class... > struct pack { };
template <class R, class T, class... Args>
int foo(pack<T>, Args...)
{
return sizeof(R);
}
template <class R, class T, class... Ts, class... Args>
int foo(pack<T, Ts...>, Args... args)
{
return foo<T>(pack<Ts...>{}, args...);
}
int main() {
// gcc: OK, clang: ambiguous
foo<int>(pack<int>{});
// gcc: ambiguous, clang: ambiguous
foo<int>(pack<int>{}, 0);
}
Run Code Online (Sandbox Code Playgroud)
如果第二个重载更改为包含至少2种类型而不是至少一种类型的包,则gcc和clang都接受两个调用:
template <class R, class T, class T2, class... Ts, class... Args>
int foo(pack<T, T2, Ts...>, Args... args)
{
return foo<T>(pack<T2, Ts...>{}, args...);
}
Run Code Online (Sandbox Code Playgroud)
如果将非推导模板参数移动到推导出的模板参数,则:
template <class... > struct pack { };
template <class R, class T, class... Args>
int foo(pack<R>, pack<T>, Args...)
{
return sizeof(R);
}
template <class R, class T, class... Ts, class... Args>
int foo(pack<R>, pack<T, Ts...>, Args... args)
{
return foo(pack<T>{}, pack<Ts...>{}, args...);
}
int main() {
// gcc ok with both, clang rejects both as ambiguous
foo(pack<int>{}, pack<int>{});
foo(pack<int>{}, pack<int>{}, 0);
}
Run Code Online (Sandbox Code Playgroud)
我希望在每个版本的调用都可以.上述代码示例的预期结果是什么?
Wal*_*ter -1
我们先把问题简单化考虑一下
template <class...> struct pack {};
template <class T>
void foo(pack<T>) {}
template <class T, class... Ts>
void foo(pack<T,Ts...>) {}
int main() {
foo(pack<int>{});
}
Run Code Online (Sandbox Code Playgroud)
clang 抱怨并拒绝编译,声称void foo(pack<T>)[with T=int] 和void foo(pack<T,Ts...>)[with T=int, Ts=<>] 之间存在歧义。像这样的情况可以使用重载函数模板的部分排序来解决,它本质上是试图找到最专门的重载。
就目前的情况而言,我认为以下内容适用:
在平局的情况下,如果一个函数模板具有尾随参数包,而另一个函数模板没有,则具有省略参数的函数模板被认为比具有空参数包的函数模板更专业。
因此看来第一个应该是首选,而 clang 是错误的。
| 归档时间: |
|
| 查看次数: |
239 次 |
| 最近记录: |