我有一个类模板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
答案 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
)。