gpt4 book ai didi

c++ - 为什么模板参数推导会因重载函数而失败?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:12:42 25 4
gpt4 key购买 nike

我有一个模板函数,它应该接受一个函数指针和参数,然后使用给定的参数调用函数指针(我们称之为 Invoke )。但是,当我使用重载函数作为参数调用模板函数时,模板推导失败。

我使用了 enable_if 以便只有一个重载有效,但这没有帮助。

#include <string>
#include <type_traits>

void foo(int, int){}
void foo(std::string, std::string) {}

template <bool Val1, bool Val2, bool ...Rest>
struct And
{
enum {value = And<Val1 && Val2, Rest...>::value};
};
template <bool Val1, bool Val2>
struct And<Val1, Val2>
{
enum {value = Val1 && Val2};
};

template <typename ...Params, typename ...Args, typename = typename std::enable_if<
And<std::is_convertible<Args, Params>::value...>::value
>::type>
void Invoke(void (*fn)(Params...), Args ...args){}

int main() {
Invoke(&foo, "a", "b");
return 0;
}

试穿ideone .

编译器提示 mismatched argument pack lengths while expanding ‘std::is_convertible<Args, Params>::value’ ,当两个重载都存在时。当我注释掉 int重载,程序编译得很好,当我注释掉 std::string 时过载,演绎失败,因为 const char[]不能隐式转换为 int .

标准(C++17 标准的第 17.8.2.1.6.2 节)说明如下:

If the argument is an overload set (not containing function templates), trial argument deduction is attempted using each of the members of the set. If deduction succeeds for only one of the overload set members, that member is used as the argument value for the deduction. If deduction succeeds for more than one member of the overload set the parameter is treated as a non-deduced context.

所以我希望编译器会尝试 int重载,推论会失败。当它尝试 std::string过载,推导成功。

由于只有一个重载集成员的推导会成功,我希望它会像 int 一样继续进行。重载不存在,并且编译会像其他重载被注释掉时一样成功,但它失败了。

我哪里错了?

对标准的引用将不胜感激。

最佳答案

这里的问题是有不止一个函数可以工作。 Params... 的推导将在您到达模板的 SFINAE 部分之前发生。当它试图从 void (*fn)(Params...) 推导出 Params.. 时,它匹配 void foo(int, int)void foo(std::string, std::string)。由于它找到了多个匹配项,因此 17.8.2.1.6.2 声明它被视为非推导上下文。

由于它无法推断类型,因此您会遇到硬停止错误。 SFINAE 只发生在模板参数推导步骤之后,在这种情况下无法到达。

关于c++ - 为什么模板参数推导会因重载函数而失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56483609/

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