且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-11-10 21:01:52

std :: function 有一个贪婪的模板构造函数,将尝试从任何东西构造它传递 1 std :: function 不是非常适合用于重载分辨率。

std::function has a greedy template constructor that will attempt to construct it from anything at all you passed it1. std::function is not very suitable for use in overload resolution. It worked in one case because perfect matches are preferred to conversion, but as noted it is fragile.

注意,lambdas和 std :: function

Note that lambdas and std::function objects are unrelated types. std::function knows how to wrap a lambda, but it can wrap any copyable invokable object. Lambdas are auto-created anonymously named classes that are copyable and invokable. std::function is a class designed to type-erase invocation.

想象一下,如果你的覆盖$ c> short 和 long auto x = 2.0 short s = 2.0 将对应于 auto x = lambda std :: function< blah> f = lambda 个案。当你显式地选择类型时,你会引起一个类型转换,你选择的类型明确没有歧义。但是当你做了 auto 时,它采用了真实的类型 - 而实际类型是不明确的。

Imagine if your overrides took short and long. The auto x = 2.0 and short s = 2.0 would correspond to the auto x = lambda and std::function<blah> f = lambda cases. When you pick the type explicitly you cause a type conversion, and the types you picked explicitly had no ambiguity. But when you did auto it took the real type -- and the real type was ambiguous.

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

SFINAE or tag dispatching using std::result_of would let you handle these overrides manually.

1 在某种程度上,这是 std :: function 中的缺陷。当传入的类型是可复制 std :: result_of_t 时,它的通用构造函数应该只参与重载解析。 X(Args ...)> 可以转换为 std :: function 的结果类型。我怀疑后概念这将被添加到标准,作为后概念这是真的很容易写和表达(和很少符合代码将被它打破)。但是,在这种特殊情况下,这不会真正有用,因为 int float 并且没有办法说这个构造函数会工作,但真的不是首选的选项。

1 To a certain extent this is a flaw in std::function. Its "universal" constructor should really only participate in overload resolution when the type passed in is both copyable and std::result_of_t< X( Args... ) > can be converted to the result type of the std::function. I suspect post-concepts this will be added to the standard, as post-concepts this is really easy to both write and express (and very little conforming code will be broken by it). However, in this particular case, this would not actually help, as int and float can be converted into each other, and there are no ways to say "this constructor will work, but really it isn't a preferred option".