【发布时间】:2017-04-24 03:20:36
【问题描述】:
考虑以下人为设计的代码:
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);
}
如果将第二个重载更改为采用至少 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...);
}
如果将非推导模板参数移动到推导模板参数,则:
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);
}
我希望在每个版本中所有调用都正常。上述代码示例的预期结果是什么?
【问题讨论】:
-
我希望每个版本的所有调用都正常。 为什么? (我没有。)
-
@Walter 因为第一个重载比第二个更专业。
标签: c++ templates gcc clang language-lawyer