ISO C++ 说这些是模棱两可的,即使第一个的最差转换比第二个的最差转换要好
ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second
为什么会这样模棱两可?
// 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 中的一个表示常量,而另一个则不是。
谢谢!
第一种情况有歧义的原因是list
不是const
,所以变成this
的隐式参数有一个限定转换,另一个重载有 std::function<void(const bool&)>
到 std::function<void(bool&)>
的转换。
另一种情况没有歧义,因为在 const
情况下两个参数都有转换,但在可变情况下仅针对 _consumer
。
第一次调用有两种可能的重载解决方案,每一种都涉及一个转换:
- 选择第一个重载,转换
std::function<void(const bool&)>
→std::function<void(bool&)>
- 选择第二个重载,转换
threadsafe_list<bool>&
→const threadsafe_list<bool>&
两种转换都不比另一种更好,因为它们适用于不同的参数。
对于第二次调用,一个比另一个好,因为较差的一个将两个参数都转换(lambda 转换为 std::function
,list
转换为 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;
为什么会这样模棱两可?
// 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 中的一个表示常量,而另一个则不是。 谢谢!
第一种情况有歧义的原因是list
不是const
,所以变成this
的隐式参数有一个限定转换,另一个重载有 std::function<void(const bool&)>
到 std::function<void(bool&)>
的转换。
另一种情况没有歧义,因为在 const
情况下两个参数都有转换,但在可变情况下仅针对 _consumer
。
第一次调用有两种可能的重载解决方案,每一种都涉及一个转换:
- 选择第一个重载,转换
std::function<void(const bool&)>
→std::function<void(bool&)>
- 选择第二个重载,转换
threadsafe_list<bool>&
→const threadsafe_list<bool>&
两种转换都不比另一种更好,因为它们适用于不同的参数。
对于第二次调用,一个比另一个好,因为较差的一个将两个参数都转换(lambda 转换为 std::function
,list
转换为 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;