const最佳匹配函数与其他函数之间的歧义
Ambiguity between const best matching function and other function
让我们考虑以下示例:
#include <type_traits>
#if 1
struct X {};
struct O
{
O(X) { ; }
};
#else
struct O {};
struct X
{
operator O () { return {}; }
};
#endif
static_assert(std::is_convertible< X, O >::value);
struct S
{
void f(X) const { ; }
void f(O) { ; }
};
#include <cstdlib>
int
main()
{
S s;
s.f(X{});
return EXIT_SUCCESS;
}
报错:
error: call to member function 'f' is ambiguous
当我删除 const
-qualifier 时,错误将不复存在。如果我将 const
-qualifier 添加到 f
的第二个重载中,同样会发生同样的情况。 IE。如果两个重载同样符合 const
限定,则一切正常。
为什么会这样?
我的编译器是clang 3.8.
Mark B & 来自莫斯科的Vlad回答为什么,我只是回复你怎么给他们打电话。
您应该添加 explicit
以避免编译器隐式转换
#include <iostream>
struct X {};
struct O
{
explicit O(X) { ; }
O() = default;
O(O const &) = default;
O(O &&) = default;
};
struct S
{
void f(X) const { ; }
void f(O) { ; }
};
#include <cstdlib>
int main()
{
S s;
s.f(X{});
return EXIT_SUCCESS;
}
编辑
如果您的类型 O
在 3party 库中
您可以添加一个模板来执行此操作。
#include <iostream>
using namespace std;
struct X {};
struct O {
O(X) {
;
}
O() = default;
O(O const&) = default;
O(O&&) = default;
};
struct S {
void f(const X) const {
cout << "X" << endl;
}
void f(O) {
cout << "O" << endl;
}
};
#include <cstdlib>
template<typename TA, typename TB>
void myCall(TA a, TB b) {
((const TA &&)a).f(b);
}
template<>
void myCall(S a, O b) {
a.f(b);
}
template<>
void myCall(S a, X b) {
((const S)a).f(b);
}
int main() {
S s;
myCall(s, X());
//s.f(X());
return EXIT_SUCCESS;
}
Why is it so?
:这里的原因是因为s
对象本身的const-ness也是也在重载决议中考虑的。由于 s
是 non-const,因此需要将 const 添加到隐式 this
指针以调用 const f
。调用 non-const f
与 this
指针完全匹配,但需要通过 O 的转换构造函数从 X
隐式转换为 O
。
成员函数有隐式参数this
。
因此,要调用其中一个函数 f
,编译器需要将 this
转换为类型 const S *
或将 X
转换为 O
。
关于所有参数的转换都不是更好。所以编译器报错。
让我们考虑以下示例:
#include <type_traits>
#if 1
struct X {};
struct O
{
O(X) { ; }
};
#else
struct O {};
struct X
{
operator O () { return {}; }
};
#endif
static_assert(std::is_convertible< X, O >::value);
struct S
{
void f(X) const { ; }
void f(O) { ; }
};
#include <cstdlib>
int
main()
{
S s;
s.f(X{});
return EXIT_SUCCESS;
}
报错:
error: call to member function 'f' is ambiguous
当我删除 const
-qualifier 时,错误将不复存在。如果我将 const
-qualifier 添加到 f
的第二个重载中,同样会发生同样的情况。 IE。如果两个重载同样符合 const
限定,则一切正常。
为什么会这样?
我的编译器是clang 3.8.
Mark B & 来自莫斯科的Vlad回答为什么,我只是回复你怎么给他们打电话。
您应该添加 explicit
以避免编译器隐式转换
#include <iostream>
struct X {};
struct O
{
explicit O(X) { ; }
O() = default;
O(O const &) = default;
O(O &&) = default;
};
struct S
{
void f(X) const { ; }
void f(O) { ; }
};
#include <cstdlib>
int main()
{
S s;
s.f(X{});
return EXIT_SUCCESS;
}
编辑
如果您的类型 O
在 3party 库中
您可以添加一个模板来执行此操作。
#include <iostream>
using namespace std;
struct X {};
struct O {
O(X) {
;
}
O() = default;
O(O const&) = default;
O(O&&) = default;
};
struct S {
void f(const X) const {
cout << "X" << endl;
}
void f(O) {
cout << "O" << endl;
}
};
#include <cstdlib>
template<typename TA, typename TB>
void myCall(TA a, TB b) {
((const TA &&)a).f(b);
}
template<>
void myCall(S a, O b) {
a.f(b);
}
template<>
void myCall(S a, X b) {
((const S)a).f(b);
}
int main() {
S s;
myCall(s, X());
//s.f(X());
return EXIT_SUCCESS;
}
Why is it so?
:这里的原因是因为s
对象本身的const-ness也是也在重载决议中考虑的。由于 s
是 non-const,因此需要将 const 添加到隐式 this
指针以调用 const f
。调用 non-const f
与 this
指针完全匹配,但需要通过 O 的转换构造函数从 X
隐式转换为 O
。
成员函数有隐式参数this
。
因此,要调用其中一个函数 f
,编译器需要将 this
转换为类型 const S *
或将 X
转换为 O
。
关于所有参数的转换都不是更好。所以编译器报错。