C++编译器选择了类成员函数的错误重载

发布于 2024-11-30 01:18:50 字数 864 浏览 7 评论 0原文

我有这样的代码:

template <class T>
class Something
{
    T val;
public:
    inline Something() : val() {}
    inline Something(T v) : val(v) {}
    inline T& get() const { return val; }

    inline Something& operator =(const Something& a) { val = a.val; return *this; }
};

typedef Something<int> IntSomething;
typedef Something<const int> ConstIntSomething;

class Other
{
public:
    IntSomething some_function()
    {
        return IntSomething(42);
    }

    ConstIntSomething some_function() const
    {
        return ConstIntSomething(42);
    }
};

void wtf_func()
{
    Other o;
    ConstIntSomething s;
    s = o.some_function();
}

但是,编译器在 wtf_func() 中选择了错误的 Other::some_function() 重载(即非常量重载)。我该如何解决这个问题?请注意,由于某些原因,我无法更改 Other::some_function() 的名称。

I have this code:

template <class T>
class Something
{
    T val;
public:
    inline Something() : val() {}
    inline Something(T v) : val(v) {}
    inline T& get() const { return val; }

    inline Something& operator =(const Something& a) { val = a.val; return *this; }
};

typedef Something<int> IntSomething;
typedef Something<const int> ConstIntSomething;

class Other
{
public:
    IntSomething some_function()
    {
        return IntSomething(42);
    }

    ConstIntSomething some_function() const
    {
        return ConstIntSomething(42);
    }
};

void wtf_func()
{
    Other o;
    ConstIntSomething s;
    s = o.some_function();
}

However, the compiler picks the wrong overload of Other::some_function() in wtf_func() (i.e. the non-const one). How can I fix this? Note that for certain reasons I cannot change the name of Other::some_function().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

何时共饮酒 2024-12-07 01:18:50

o 不是 const 限定的,因此选择非 const some_function。如果要选择 const 限定的重载,则需要在 o 上添加 const 限定符:

Other o;
Other const& oref(o);
ConstIntSomething s;
s = oref.some_function();

当重载决策发生时,编译器只查看 o.some_function() > 子表达式;它不会查看函数调用周围的上下文来决定选​​择其他内容。此外,在重载决策期间不考虑成员函数的返回类型。

请注意,将 IntSomething 隐式转换为 ConstIntSomething 可能更有意义,可以使用 IntSomething 中的 operator ConstIntSomething() 重载 (不太好)或使用非显式的 ConstIntSomething(IntSomething const&) 构造函数ConstIntSomething(更好)。

o is not const-qualified, so the non-const some_function is selected. If you want to select the const-qualified overload, you need to add the const qualifier to o:

Other o;
Other const& oref(o);
ConstIntSomething s;
s = oref.some_function();

When overload resolution occurs, the compiler only looks at the o.some_function() subexpression; it does not look at the context around the function call to decide to pick something else. Further, the return type of a member function is not considered during overload resolution.

Note that it may make more sense for IntSomething to be implicitly convertible to ConstIntSomething, either using an operator ConstIntSomething() overload in IntSomething (less good) or using a non-explicit ConstIntSomething(IntSomething const&) constructor in ConstIntSomething (more good).

情绪 2024-12-07 01:18:50

它不会选择错误的过载; const-ness 通过 this 是否为 const 来解析。在您的情况下,o 是非const,因此选择非const 重载。

您可以通过创建对 o 的常量引用来破解此问题,例如:

const Other &o2 = o;
s = o2.some_function();

但实际上,您可能应该考虑 Something 中的重载。例如,您目前无法执行此操作:

IntSomething x;
ConstIntSomething y;
y = x;

这听起来不正确。为什么不应该允许您将 const 引用传递给非常量引用?

It doesn't pick the wrong overload; const-ness is resolved by whether this is const or not. In your case, o is non-const, so the non-const overload is picked.

You can hack this by creating a const-reference to o, e.g.:

const Other &o2 = o;
s = o2.some_function();

But really, you should probably be considering your overloads in Something. For instance, you can't currently do this:

IntSomething x;
ConstIntSomething y;
y = x;

which doesn't sound correct. Why shouldn't you be allowed to take a const ref to a non-const ref?

东北女汉子 2024-12-07 01:18:50

您的对象 o 必须是 const 对象,才能在其上调用 const 函数。否则,编译器会正确地选择该函数的非 const 版本。

Your object o needs to be const object for a const function to be called on it. Otherwise the compiler rightly picks up the non const version of the function.

沫尐诺 2024-12-07 01:18:50

编译器根据将成为 this 的对象的常量性来选择要使用的重载。您可以使用 static_cast 使其调用所需的版本:s = static_cast(o.some_function());

The compiler picks the overload to use based on the constness of the object that will become this. You can make it call the desired version with static_cast: s = static_cast<const Other&>(o.some_function());

淡莣 2024-12-07 01:18:50

您可能还想复制 C++0x 标准库容器中的新行为。像 Vector 这样的容器现在具有成员 cbegin()cend(),无论容器是否为 const,它们都会返回 const_iterator,这与 begin() 不同和end()

class Other {
    // Rest of other
public:
    // No overload for non-const
    // Even if called with a non const Other, since this member is marked
    // const, this will be of type Other const * in all cases and will call
    // the const qualified overload of some_function.
    ConstIntSomething csome_function() const
    {
        return some_function();
    }
};

You might also want to copy the new behaviour found in the containers of the C++0x standard library. Containers such as vector now have members cbegin() and cend() that return a const_iterator whether the container is const or not unlike begin() and end()

class Other {
    // Rest of other
public:
    // No overload for non-const
    // Even if called with a non const Other, since this member is marked
    // const, this will be of type Other const * in all cases and will call
    // the const qualified overload of some_function.
    ConstIntSomething csome_function() const
    {
        return some_function();
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文