ISO C++表示,这些都是模糊的,尽管第一个的最差转换比第二个的最坏转换要好



为什么这不明确?

// In class declaration
template<typename T>
class threadsafe_list {
void for_each(std::function<void(T&)> _consumer);
void for_each(std::function<void(const T&)> _consumer) const;
}
// Calling for_each
threadsafe_list<bool> list;
std::function<void(const bool&)> print = [](const bool& _bool) {
std::cout << (_bool ? "True" : "False") << std::endl;
};
// Warning: for_each is ambiguous
list.for_each(print);
// This is OK
list.for_each([](const bool& _bool) { std::cout << (_bool ? "True" : "False") << std::endl; }); 

为什么会出现上述歧义?其中一个for_each用于const,而另一个不是。谢谢

第一次调用有两种可能的过载解决方案,每种方案都涉及一个转换:

  1. 选择第一个重载,转换std::function<void(const bool&)>std::function<void(bool&)>
  2. 选择第二个过载,转换threadsafe_list<bool>&const threadsafe_list<bool>&

两种转换都不如另一种,因为它们适用于不同的参数。

对于第二个调用,其中一个比另一个好,因为较差的一个会转换两个参数(lambda转换为std::functionlist转换为const threadsafe_list<bool>&(。

为了解决这个问题,你可以添加另一个重载,这将比原来的两个更好地匹配:

void for_each(std::function<void(T&)> _consumer) const;

或者,也可以完全删除std::function,以确保参数的完全匹配:

template <typename F>
void for_each(F _consumer);
template <typename F>
void for_each(F _consumer) const;

第一种情况中存在歧义的原因是list不是const,因此成为this的隐式参数具有限定转换,而另一个重载具有std::function<void(const bool&)>std::function<void(bool&)>的转换。

另一种情况并不含糊,因为在const的情况下,两个参数都有转换,但在可变的情况下仅对_consumer有转换。

相关内容

最新更新