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

Ste*_*mer 2 c++ pointers compiler-errors const

我有一个Foo具有以下成员函数的类模板:

bool contains(const T& item) const
Run Code Online (Sandbox Code Playgroud)

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

bool contains(const Bar*& item) const
Run Code Online (Sandbox Code Playgroud)

const Bar成员函数中,我尝试传递thisFoo<Bar*>::contains:

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

这无法编译,出现以下错误:

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

题:

  • 为什么我的const T&参数不是常量的?
  • 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);
    }
};
Run Code Online (Sandbox Code Playgroud)

错误输出:

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
Run Code Online (Sandbox Code Playgroud)

Yam*_*vic 5

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

bool contains(const Bar*& item) const
Run Code Online (Sandbox Code Playgroud)

这就是问题所在.什么时候T = Bar*,表达

bool contains(const T& item) const
Run Code Online (Sandbox Code Playgroud)

实际上会编译到

bool contains(Bar * const & item) const
Run Code Online (Sandbox Code Playgroud)

也就是说,引用一个const-pointer-to-Bar.你想到它是有意义的:你想要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);
};
Run Code Online (Sandbox Code Playgroud)