我在模板类中遇到函数定义问题。
我有一个模板类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
或类似的其他人来拥有动态调整大小的数组。这可以带来所有的乐趣。
答案 0 :(得分:2)
实际上,您对该功能的声明可以被视为:
IndexOf(const (Object *) val)
这基本上意味着Object *
应该指向const对象:
Object *const cobj = new Object();
现在你将有正确的行为。 但是,如果您对const指针感兴趣,那么您需要将声明修改为:
Array<const Object *> objects;
答案 1 :(得分:0)
const T value
T
Object*
Object* const value
为const
。 const T value
中的value
适用于T
,不会修改const T value
。 value
是类型T
的{{1}},无法更改,指针无法为其分配新地址。很明显,使用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>;
答案 2 :(得分:0)
您可以将Array<Object*>::IndexOf()
声明为模板:
template <typename U>
int IndexOf(const U& value) const {
// Code of function
}
并在里面将value
与数组的内容进行比较,该比较会将内容从Object*
转换为const Object*
,这当然是允许的。
使用这种方法,您可以将T
可以转换为/的任何内容传递给该函数。