将const传递给函数接受const指针不是const-correct?

时间:2016-01-25 19:30:52

标签: c++ pointers compiler-errors const

我有一个类模板Foo,其中包含以下成员函数:

bool contains(const T& item) const

我用指针类型Foo<Bar*>实例化了这个,导致我期望成员函数现在具有以下签名:

bool contains(const Bar*& item) const

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

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

编译失败,出现以下错误:

  

错误:从“const Bar*”到“Bar*

的转换无效

问题:

  • 为什么我的const T&参数不是const-correct?
  • 需要Foo<T>::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

2 个答案:

答案 0 :(得分:5)

  

我用指针类型实例化了这个:Foo<Bar*>,引导我   期望成员函数现在具有以下内容   签名:

bool contains(const Bar*& item) const

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

bool contains(const T& item) const

实际编译到

bool contains(Bar * const & item) const

即,引用指向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);
};

答案 1 :(得分:0)

关于错误行的编译器警报,你必须写:

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

即。模板参数中的const Bar*,因为Bar::func接收const Bar * this作为参数,并且无法将其转换为模板参数中的Bar*(无法删除const)。