gpt4 book ai didi

c++ - 不明确的重载 - 带有参数包的部分函数模板排序

转载 作者:可可西里 更新时间:2023-11-01 16:18:49 26 4
gpt4 key购买 nike

考虑以下人为设计的代码片段:

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);
}

如果将第二个重载更改为采用至少两种类型的包而不是至少一种类型的包,则 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);
}

我希望所有调用在每个版本中都能正常运行。以上代码示例的预期结果是什么?

最佳答案

我现在相信 clang 拒绝是正确的,而 gcc 接受它所做的那些形式是不正确的。这是一个简化的示例:

template <class...> struct pack { };

// (1)
template <class T>
void foo(pack<T> ) { }

// (2)
template <class T, class... Ts>
void foo(pack<T, Ts...> ) { }

int main() {
foo(pack<int>{});
}

两个重载都是有效的,从 (1) 推导 (2) 直接成功。唯一的问题是我们能否从 (2) 中推导出 (1)。我最初认为不......但是 [temp.deduct.type]/9 状态:

If P has a form that contains <T> or <i>, then each argument Pi of the respective template argument list of P is compared with the corresponding argument Ai of the corresponding template argument list of A. [...] During partial ordering (14.8.2.4), if Ai was originally a pack expansion:
— if P does not contain a template argument corresponding to Ai then Ai is ignored;

所以当我们为 <T, Ts...> 合成类型时(比如说 <U, Xs...> ),我们推导出 T=U然后没有与包扩展对应的模板参数 Xs... ,所以我们忽略它。所有未忽略的模板参数都成功进行了模板推导,因此我们认为从 (2) 推导 (1) 是成功的。

由于推导在两个方向上都成功了,所以没有一个函数模板被认为比另一个更专业,调用应该是有歧义的。


我还没有提交错误报告,等待社区的确认。

关于c++ - 不明确的重载 - 带有参数包的部分函数模板排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41046986/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com