【问题标题】:passing const this to function accepting const pointer is not const-correct?将 const this 传递给接受 const 指针的函数不是 const 正确的吗?
【发布时间】:2016-01-25 19:30:52
【问题描述】:

我有一个类模板Foo,其成员函数如下:

bool contains(const T& item) const

我已经用指针类型实例化了它:Foo<Bar*>,这让我期待成员函数现在具有以下签名:

bool contains(const Bar*& item) const

constBar 成员函数中,我尝试将this 传递给Foo<Bar*>::contains

bool Bar::func(const Foo<Bar*>& foo) const
{
    return foo.contains(this);
}

编译失败,报错:

错误:从“const Bar*”到“Bar*”的转换无效

问题:

  • 为什么我的 const T&amp; 参数不是 const 正确的?
  • 需要Foo&lt;T&gt;::contains(...) const 的什么签名才能允许使用this 调用编译?

完整示例:

#include <vector>
#include <algorithm>

template<typename T>
struct Foo
{
    bool contains(const T& item) const
    {
        return false;
    }
};

struct Bar
{
    bool func(const Foo<Bar*>& foo) const
    {
        return foo.contains(this);
    }
};

错误输出:

scratch/main.cpp:17:33: error: invalid conversion from ‘const Bar*’ to ‘Bar*’ [-fpermissive]
         return foo.contains(this);
                                 ^
scratch/main.cpp:7:10: note: initializing argument 1 of ‘bool Foo<T>::contains(const T&) const [with T = Bar*]’
     bool contains(const T& item) const

【问题讨论】:

    标签: c++ pointers compiler-errors constants


    【解决方案1】:

    我已经用指针类型实例化了它:Foo&lt;Bar*&gt;,引导我 期望成员函数现在将具有以下内容 签名:

    bool contains(const Bar*& item) const
    

    这就是问题所在。当T = Bar*时,表达式

    bool contains(const T& item) const
    

    实际上会编译成

    bool contains(Bar * const & item) const
    

    也就是说,一个对一个常量指针的引用。 你想想就明白了:你想让 T 成为 const,然后你想要一个对它的引用。

    如果您想以通常的“预期”方式应用 const(尽管这可能会给经验丰富的 C++ 程序员带来一些意外),您可以通过以下方式声明您的容器和成员函数:

    template <class T>
    class Container {
    public:
        using const_bare_type = typename std::conditional<
            std::is_pointer<T>::value,
            typename std::remove_pointer<T>::type const*,
            const T>::type;
    
        bool contains(const const_bare_type& item);
    };
    

    【讨论】:

    • 我能否对我的Foo 成员函数进行任何更改,以便将this 传递给它?
    • @SteveLorimer 不,实例化Foo&lt;Bar*&gt; 时发生错误,请参阅我的答案。
    • @YamMarcovic 看起来像是作弊 ;-)
    • @SteveLorimer 有点像。您不一定需要有 2 个重载。在类定义中,您可以使用一些特征来定义const_bare_type,这将产生const T 用于非指针类型,const T* 用于指针类型。然后声明contains(const_bare_type&amp; item)
    • @SteveLorimer 我为最后一位添加了一些示例代码,并删除了过度专业化的指针内容。
    【解决方案2】:

    编译器提示错误的行,你必须写:

    bool func(const Foo<const Bar*>& foo) const
    

    const Bar*在模板参数中,因为Bar::func接收const Bar * this作为它的参数,并且不能将它转换为模板参数中的Bar*(不能删除const)。

    【讨论】:

    猜你喜欢
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    • 2016-05-18
    • 1970-01-01
    • 2014-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多