C ++中的数组模板类

时间:2018-03-31 11:07:33

标签: c++ arrays templates return return-type

我无法理解如何在C ++中正确创建Array模板类。 问题完全出于学习目的。

让我先提供代码。

Array.h

//Developed by Trofimov Yaroslav on 30.03.2018

#ifndef _ARRAY_H_TROFIMOV_
#define _ARRAY_H_TROFIMOV_

#include <string>

template<const size_t n, typename T>
class Array {
    static unsigned __freeId, __quantity;
    unsigned _id;

    T** _array;
    const size_t _n;
public:
    typedef const bool (* const BooleanResultDelegate)(const T&);
    class ArrayError {
        const std::string _reason;
        const size_t _index;
        const size_t _maxIndex;
    public:
        ArrayError(const size_t index, const size_t maxIndex,const std::string& reason = "") 
            : _index(index), _maxIndex(maxIndex), _reason(reason) {}
        std::string explanation(void) {
            std::string res += "Index: " + std::to_string(_index) + "\n"; 
            res += "Max index: " + std::to_string(_maxIndex) + "\n"; 
            res += "Reason: " + _reason + "\n"; 
            return res;
        }
    };

    explicit Array<n, T>(T* arrayFiller = 0) 
        : _n(n), _array(new T*[n]), _id(++__freeId) {
            if(arrayFiller != 0) {
                for(size_t i(0); i < length(); ++i) {
                    _array[i] = new T(*arrayFiller);
                }
            } else {
                for(size_t i(0); i < length(); ++i) {
                    _array[i] = arrayFiller;
                }
            }
            reportIfDebug<n, T>(*this, "created");
            ++__quantity;
    }
    explicit Array<n, T>(const T& arrayFiller) 
        : _n(n), _array(new T*[n]), _id(++__freeId) {
            for(size_t i(0); i < length(); ++i) {
                _array[i] = new T(arrayFiller);
            }
            reportIfDebug<n, T>(*this, "created");
            ++__quantity;
    }
    Array<n, T>(const Array<n, T>& that) 
        : _n(n), _array(new T[n]), _id(++__freeId) {
            for(size_t i(0); i < length(); ++i) {
                (*this)[i] = new T[that[i]];
            }
            reportIfDebug<n, T>(*this, "created");
            ++__quantity;
    }
    ~Array<n, T>(void) {
        removeAll();
        delete [] _array; _array = 0;
        reportIfDebug<n, T>(*this, "deleted", false);
        --__quantity;
    }

    T* operator[](const size_t i) {
        if(i > length()) {
            throw ArrayError(i, _n, "out of bounds exception");
        }
        return _array[i];
    }
    const T* operator[](const size_t i) const {
        if(i > length()) {
            throw ArrayError(i, _n, "out of bounds exception");
        }
        return _array[i];
    }
    const size_t length() const {
        return _n;
    }
    const unsigned getID() const {
        return _id;
    }

    void removeAll(BooleanResultDelegate removeCondition = 0) {
        for(size_t i(0); i < length(); ++i) {
            if(removeCondition == 0 || removeCondition(*_array[i])) {
                delete [] _array[i]; _array[i] = 0;
            }
        }
    }
};

template<const size_t n, typename T>
unsigned Array<n, T>::__freeId(0);
template<const size_t n, typename T>
unsigned Array<n, T>::__quantity(0);

template<const size_t n, typename T>
void reportIfDebug(
    const Array<n, T>& instance, 
    const char* const message, 
    const bool showContent = true) {
#ifndef NDEBUG
    std::cout << "========================================" << std::endl;
    std::cout << typeid(instance).name() << ' ' 
        << message << ' '
        << "id: " << instance.getID() << std::endl;
    if(showContent) {
        std::cout << instance;
    }
    std::cout << "========================================" << std::endl;
#endif
}
template<const size_t n, typename T>
std::ostream& operator<<(std::ostream& os, const Array<n, T>& instance) {
    for(size_t i(0); i < instance.length(); ++i) {
        if(instance[i] == 0) {
            os << "[" << i << "]: " << instance[i] << "\n";
        } else {
            os << "[" << i << "]: " << *instance[i] << "\n";
        }
    }
    return os;
}
#endif

Main.cpp

//Developed by Trofimov Yaroslav on 30.03.2018
#include <iostream>
#include "Array.h"

int main(void) {
    const Array<5, int> a(7);
    std::cout << *a[2] << std::endl;
    return 0;
}

现在的主要问题是 - 我的Array类的客户端必须使用[间接运算符*]和[0值指针检查]才能使用数组中的对象。

我不希望客户这样做。但是,如果我使用引用而不是指针作为operator[]的返回类型,我将无法返回没有复制构造函数的类型,如果之前没有任何内容,我将返回垃圾。

似乎在JavaC#中问题也没有解决。用户在那里获得对象的引用,并且肯定应检查返回的null。并且[间接运算符*]在那里自动调用。

0 个答案:

没有答案