[英]Const being ignored in template function parameter list
我在模板类中的函数定义有问题。
我有一个模板类Array
,它具有成员函数IndexOf
:
// Defined in header
template <typename T>
class Array {
// Other stuff
int IndexOf(const T value) const {
// Code of function
};
// Other stuff
};
当我使用类指针创建数组的实例时,该函数将忽略 const T
并仅使用T
因此,当我使用const T
调用函数时,会出现编译器错误:“无重载函数实例”:
#include "Array.h"
class Object{
// Object stuff
};
int main(){
// Demonstration code
Array<Object*> objects = Array<Object*>(); // Array of Object*
Object* obj = new Object(); // An Object*
const Object* cobj = new Object(); // A const Object*
// This works fine
objects.IndexOf(obj); // No problems
// This has compile error
objects.IndexOf(cobj); // No idea why
delete obj;
delete cobj;
return 0;
}
代码似乎忘记了函数的参数是const T
函数参数应为const Object*
,但它将参数视为仅Object*
。
知道为什么会这样吗?
如果我没有使用指针作为类型,则不会发生该错误。
函数内部的代码不会引起问题。
在不说之前,我不会使用std::vector
或其他类似的东西来动态调整数组大小。 那会带走所有的乐趣。
实际上,您对函数的声明可以视为:
IndexOf(const (Object *) val)
这基本上意味着Object *
应该指向const对象,如下所示:
Object *const cobj = new Object();
现在您将具有正确的行为。 但是,如果您真的对const指针感兴趣,则需要将声明修改为:
Array<const Object *> objects;
const T value
其中T
是Object*
是Object* const value
。 该const
在const T value
适用于value
并不会修改T
。 const T value
是不能更改的T
类型的value
,对于指针而言,这意味着无法分配新的地址。 显然,以下函数不能用const Object *
调用。
int IndexOf(Object * const value) const // const pointer to non-const Object
要为指向类型添加const
,可以使用type-traits获取指向类型,向其添加const,然后从中生成新的指针类型。 例如 :
#include <type_traits>
template<class T>
using add_const_to_ptr =
std::add_pointer_t<
std::add_const_t<
std::remove_pointer_t<T>>>;
其用法如下所示:
template<class T>
struct container {
void push(add_const_to_ptr<T> ptr) {
(void)ptr;
}
};
struct bar {};
int main()
{
const bar cbar;
bar mbar;
container<bar*> my_container;
my_container.push(&mbar);
my_container.push(&cbar);
}
尽管这假定container
将仅与指针一起使用,在这种情况下,最好使T
引用指向的对象类型,而不是指针类型。 如果T
可能是或不是指针类型,则可以通过检查T
是否实际上是带有std::conditional
的指针来改进类型特征:
#include <type_traits>
template<class T>
using add_const_to_ptr =
std::conditional_t<std::is_pointer<T>::value,
std::add_pointer_t<
std::add_const_t<
std::remove_pointer_t<T>>>,
T>;
您可以将Array<Object*>::IndexOf()
为模板:
template <typename U>
int IndexOf(const U& value) const {
// Code of function
}
在内部,您将把value
与数组的内容进行比较,并且这种比较会将内容从Object*
const Object*
为const Object*
,这当然是允许的。
同样,使用这种方法,您可以将可以从T
转换为/转换为T
任何东西传递给该函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.