ISO C++ 表示这些是不明确的,尽管第一个的最差转换比第二个的最差转换要好

问题描述 投票:0回答:3

为什么会出现这样的歧义?

// 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 的,而另一个则不是。 谢谢!

c++ language-lawyer
3个回答
7
投票

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

  1. 选择第一个重载,转换
    std::function<void(const bool&)>
    std::function<void(bool&)>
  2. 选择第二个重载,转换
    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;

2
投票

第一种情况存在歧义的原因是

list
不是
const
,因此变为
this
的隐式参数具有限定转换,而另一个重载具有
std::function<void(const bool&)>
std::function<void(bool&)>
转换.

另一种情况并不含糊,因为在

const
情况下两个参数都有转换,但仅适用于可变情况下的
_consumer


0
投票

我有两个构造函数,简化符号如下:

#define A -1
class_name::constructor_name(const char* a, std::streamsize b);
//std::streamsize being 'long long'

class_name::constructor_name(char* a, int b);
...

constructor_name((const char*)"abc", A);

我遇到了该线程中提到的错误。我通过将 A 转换为 std::streamsize:

解决了这个问题
constructor_name((const char*)"abc", (std::streamsize) A);
© www.soinside.com 2019 - 2024. All rights reserved.