Я пытаюсь узнать о шаблонах и специализации шаблонов. Я пишу класс шаблона для массивов, используя специализацию шаблонов, чтобы избежать раздувания кода. Таким образом, у меня есть полностью специализированный шаблон MyArray, а затем я наследую его от class MyArray<T*> : private MyArray<void*>
. У меня возникли проблемы с перегрузкой индексированных операторов (один для non-const refs, один для const refs). Вот фрагмент кода (далеко не полный, но содержит мою проблему).Перегрузка оператора для частичной специализации шаблона
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
/*** template class MyArray **/
template <class T>
class MyArray {};
/*** Full template specialization for MyArray holding pointers ***/
template <>
class MyArray<void*> {
public:
explicit MyArray(unsigned s = 100) : sz(s) {
data = new void*[s];
}
virtual ~MyArray() { delete[] data; }
/** subscript operator overload for non-const refs **/
void*& operator[](unsigned i) {
return data[i];
}
/** subscript operator overload for const refs **/
const void*& operator[](unsigned i) const {
return data[i]; // line 26
}
unsigned size() const { return sz; }
private:
void** data;
unsigned sz;
};
/** Partial specialization: create the template class by inheriting from the one above **/
template <class T>
class MyArray<T*> : private MyArray<void*> {
public:
explicit MyArray(unsigned s = 100) : MyArray<void*>::MyArray(s) {
data = new T*[s];
}
virtual ~MyArray() { delete[] data; }
/** subscript operator overload for non-const refs **/
T*& operator[](unsigned i) {
return reinterpret_cast<T*&>( // line 47
MyArray<void*>::operator[](i)
);
}
/** subscript operator overload for const refs **/
const T*& operator[](unsigned i) const {
return reinterpret_cast<const T*&>(
MyArray<void*>::operator[](i)
);
}
unsigned size() const { return MyArray<void*>::size(); }
private:
T** data;
};
/** input function for filling MyArray's **/
template <class T>
void InputMyArray(MyArray<T*>& my_array) {
unsigned size = 0;
T tmp;
while (cin >> tmp) {
T* i = new T;
*i = tmp;
my_array[size++] = i;
}
}
/** output function for printing elements of MyArray's **/
template <class T>
void OutputArray(const MyArray<T*>& my_array) {
for (unsigned i = 0; i < my_array.size(); i++) {
cout << *my_array[i] << " ";
}
cout << endl;
}
int main() {
/** Initialize array, fill it, print contents **/
MyArray<int*> p;
InputMyArray(p);
cout << "MyArray of pointer to ints holds int values: " << endl;
OutputArray(p);
return 0;
}
Компилятора (лязг) жалуется (ошибка) около линии 26
Неконстантной именующей ссылка на тип «константный пустот *» не может связываться с величиной несвязанного типа «недействительными *»
Я полагаю, что я не хочу, чтобы компилятор интерпретировал это как неконстантную ссылку - я хочу, чтобы он был const. Как я могу правильно перегрузить этот оператор в этом контексте? Соответствующий фрагмент кода отлично работает для класса шаблона без специализации, например MyArray<T>
.
Компилятор далее жалуется (предупреждения) о reinterpret_cast
с, по-видимому содержат неопределенное поведение
reinterpret_cast от 'пустоты *' до 'междунар * &' имеет неопределенное поведение
(линия 47). reinterpret_casts
по существу скопированы с моих инструкций, поэтому я думаю, что они будут использоваться так. Не знаю, почему ссылка на void*
не поднята. Что я здесь делаю неправильно?
[OT]: Ваше наследство кажется странным, как вы не факторизовать кода, дублирующие пользователей (переменная и метод) ... и вы вводите литье, тогда как код может быть безопасным ... – Jarod42
Даже если вам удастся скомпилировать это, каждый из ваших объектов будет иметь два элемента данных. Тот, который используется, также скрыт другим. – qPCR4vir
Реорганизация вашего кода и использование нескольких способов использования сделают все проще. – qPCR4vir