const最佳匹配函数与其他函数之间的歧义

时间:2016-01-15 17:01:01

标签: c++ overloading

让我们考虑以下示例:

#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 - 限定符时,错误就不复存在了。如果我将const - 限定符添加到f的第二次重载,同样会发生同样的情况。即如果两个重载都相同const - 合格,则一切正常。

为什么会这样?

我的编译器是 clang 3.8

3 个答案:

答案 0 :(得分:2)

Why is it so?:这里的原因是因为s对象本身的常量在重载决策中也是 。由于s是非const,因此需要将const添加到隐式this指针以调用const f。调用非const fthis指针完全匹配,但需要通过O的转换构造函数从X隐式转换为O

答案 1 :(得分:2)

成员函数具有隐式参数this

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

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

答案 2 :(得分:1)

马克B &amp; 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在3方lib中 您可以添加模板来执行此操作。

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