gpt4 book ai didi

C++11 auto、std::function 和对重载函数的模糊调用

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

我想知道是否有人知道为什么以下示例无法编译并给出对重载函数错误的模糊调用。如果我用强类型仿函数签名替换 auto,它就能够正确区分两个方法重载。

我注意到当不使用 std::function 作为我的重载参数时,不会发生同样的问题。如果我的重载只接受一个简单的 float 和 int,即使使用 auto 关键字定义我的输入参数,编译器也可以正确区分这两个重载。我正在 VisualStudio 2012 中编译它。这可能只是 VS 编译器中的错误吗?我现在无法访问装有 GCC 或 Clang 的机器,但有人知道这是否可以在那里编译吗?

编译错误:对重载函数的调用不明确

class AmbiguousOverload
{
public:
static void OverloadedMethod(std::function<int()>) {}
static void OverloadedMethod(std::function<float()>) {}
};

int _tmain(int argc, _TCHAR* argv[])
{
auto func1 = []() -> float {
return 0.5f;
};

auto func2 = []() -> int {
return 12;
};

AmbiguousOverload::OverloadedMethod(func1);
AmbiguousOverload::OverloadedMethod(func2);

return 0;
}

编译

class AmbiguousOverload
{
public:
static void OverloadedMethod(std::function<int()>) {}
static void OverloadedMethod(std::function<float()>) {}
};

int _tmain(int argc, _TCHAR* argv[])
{
std::function<float()> func1 = []() -> float {
return 0.5f;
};

std::function<int()> func2 = []() -> int {
return 12;
};

AmbiguousOverload::OverloadedMethod(func1);
AmbiguousOverload::OverloadedMethod(func2);

return 0;
}

也编译

class AmbiguousOverload
{
public:
static void OverloadedMethod(int) {}
static void OverloadedMethod(float) {}
};

int _tmain(int argc, _TCHAR* argv[])
{
auto v1 = 0.5f;
auto v2 = 12;

AmbiguousOverload::OverloadedMethod(v1);
AmbiguousOverload::OverloadedMethod(v2);

return 0;
}

最佳答案

std::function有一个贪心template构造函数,它将尝试从您传递给它的任何东西构造它1std::function不太适合用于重载决议。它在一种情况下起作用,因为完美匹配优于转换,但如前所述,它很脆弱。

请注意 lambda 和 std::function对象是不相关的类型。 std::function知道如何包装 lambda,但它可以包装任何可复制的可调用对象。 Lambda 是自动创建的匿名命名类,可复制和调用。 std::function是一个旨在类型删除调用的类。

想象一下,如果您的覆盖占用了 shortlong . auto x = 2.0short s = 2.0将对应于 auto x = lambdastd::function<blah> f = lambda个案。当您显式选择类型时,您会导致类型转换,并且您显式选择的类型没有歧义。但是当你做了auto它采用了真实类型——而真实类型是不明确的。

SFINAE 或标签调度使用 std::result_of会让您手动处理这些覆盖。

这有点改变。现在构造函数只尝试吞下兼容 参数。但是一个返回 int 的函数和一个返回 float两者相互兼容,因此对您的具体情况没有帮助。


1 在一定程度上这是std::function的缺陷.当传入的类型既可复制又可复制时,它的“通用”构造函数实际上应该只参与重载决策 std::result_of_t< X( Args... ) >可以转换为 std::function 的结果类型.我怀疑后概念这将被添加到标准中,因为后概念这真的很容易编写和表达(并且很少有符合规范的代码会被它破坏)。然而,在这种特殊情况下,这实际上并没有帮助,因为 intfloat可以相互转换,并且没有办法说“这个构造函数可以工作,但实际上它不是一个首选选项”。

关于C++11 auto、std::function 和对重载函数的模糊调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22542780/

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