[英]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.