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;
}

Live example

报错:

 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 fthis 指针完全匹配,但需要通过 O 的转换构造函数从 X 隐式转换为 O

成员函数有隐式参数this

因此,要调用其中一个函数 f,编译器需要将 this 转换为类型 const S * 或将 X 转换为 O

关于所有参数的转换都不是更好。所以编译器报错。