Как преобразовать пользовательский вектор <typename>в вектор STL <long>и без изменения заданного кода? - PullRequest
0 голосов
/ 07 июня 2019

У меня проблема с домашним заданием, когда я должен реализовать интерпретатор для языка программирования GritVM. Я собрал программу, и она работает с использованием списка STL и вектора в соответствии с требованиями первого вопроса, но в части 2.Необязательный вопрос попросил меня реализовать свой собственный класс векторных шаблонов и реализовать его поверх этого GritVM.hpp & GritVM.cpp (реализация на основе orignal STL) без изменения параметров функции или элементов данных, с которых я начал.

Пока что я создал собственный векторный класс с именем ArrayVector.И сделали все основные ADT вектора, используя структуру данных массива.Я застрял в двух местах.Мое преобразование из и в STL не работает.Мне было интересно, если кто-нибудь может мне помочь.Я могу предоставить больше кода, если вам нужно больше информации.Заранее спасибо.

Я получаю следующие ошибки:

GritVM.cpp: In member function 'virtual STATUS GritVM::load(std::__cxx11::string, const std::vector<long int>&)':
GritVM.cpp:56:14: error: binding 'const std::vector<long int>' to reference of type 'std::vector<long int>&' discards qualifiers
  myDataMem = initialMemory;
              ^~~~~~~~~~~~~
In file included from GritVM.hpp:7:0:
ArrayVector.hpp:47:18: note:   initializing argument 1 of 'ArrayVector<Object>& ArrayVector<Object>::operator=(std::vector<Object>&) [with Object = long int]'
     ArrayVector& operator= (std::vector<Object>& stlv){
                  ^~~~~~~~
ArrayVector.hpp: In instantiation of 'std::vector<Object>& ArrayVector<Object>::tempVec_to_stlVec() [with Object = long int]':
GritVM.cpp:17:37:   required from here
ArrayVector.hpp:53:41: error: conversion from 'long int*' to non-scalar type 'std::vector<long int>' requested
         std::vector<Object> to_stdVec = Arr;
                                         ^~~
ArrayVector.hpp:53:29: warning: reference to local variable 'to_stdVec' returned [-Wreturn-local-addr]
         std::vector<Object> to_stdVec = Arr;

ArrayVector.hpp

/********ArrayVector.hpp template class************/

/*Base is given by the book author, it includes enum data
for instructions and machine code. I can give you the code for the base file too*/

#include "GritVMBase.hpp"

template<typename Object>
class ArrayVector{

private:
    int capacity;
    auto num_longElem;
    Object* Arr;
protected:
public:
    friend class GritVM;

    ArrayVector() : capacity(0), num_longElem(0), Arr(nullptr) { }

    ArrayVector(std::vector<Object>& stl_vector_para){ 
       Arr = stl_vector_para;
       capacity = stl_vector_para.capacity();
       num_longElem = stl_vector_para.size();
    };

    ~ArrayVector(){
        delete [] Arr;
    }

    ArrayVector(const ArrayVector& av){ 
        capacity =  av.capacity;
        num_longElem = av.num_longElem;
        Arr = new Object [capacity];
        for(auto x = 0; x < num_longElem; ++x){ 
            Arr[x] = av.Arr[x];
        }
    }

    ArrayVector& operator= (ArrayVector& av){
        ArrayVector copy = av;
        std::swap(*this, copy);
        return *this;
    }

    /***********NOT SURE ABOUT THESE TWO!!!*************/
    ArrayVector& operator= (std::vector<Object>& stlv){
        ArrayVector copy = stlv;
        std::swap(*this, copy);
        return *this;
    }
    std::vector<Object>& tempVec_to_stlVec(ArrayVector& av){
        std::vector<Object> to_stdVec = av;
        return to_stdVec;
    }
    /***************************************************/
     Object& at(auto index){
        if(index < 0 || index > num_longElem){
            throw ("Out of bound access.\n");
        }
        return Arr[index];
    }

    void erase(auto index){
        if(index < 0 || index > num_longElem){
            throw ("erase() failed.\n");
        }
        for(auto x = index + 1; x < num_longElem; ++x){
            Arr[x-1] = Arr[x];
        }
        --num_longElem;
    }

    void insert(auto index, const Object& le){
        if(num_longElem >= capacity){
            reserve(std::max(1 , 2*capacity));
        }
        for(auto x = num_longElem-1; x >= index; --x){
            Arr[x+1] = Arr[x];
        }
        Arr[index] =  le;
        ++num_longElem;
    }
/*...then some more basic ADT like size(), empty(), reserve(), empty() etc...*/
};

GritVM.hpp

#include "ArrayVector.hpp"
#include "GritVMBase.hpp"

class GritVM : public GritVMInterface {
private:
    long accumulator; /*Stores the result*/
    STATUS machineStatus; /*Gets the enum data from Machine Status*/

    std::list<Instruction>::iterator currentInstruct; /*Iterator that runs on enum data*/
    std::list<Instruction> instructMem;/*Adds the instruction*/
    std::vector<long> dataMem; /*Data memory, can't be erased or changed*/

    ArrayVector<long> myDataMem; /*TRYING TO GET THIS IMPLEMENTED ALONG SIDE STL VECTOR dataMem*/

    long evaluate(Instruction current_instruction); /*Does arithmatic based on instruction*/
    void advance(long move_instruction_amount); /*Advances the machine instruction*/
protected:
public:
    GritVM(); /*Default constructor*/
    ~GritVM() { } /* Default destructor*/

    /*Assignment realated overridden functions, were pure virtial functions, the parameters can't be changed*/
    STATUS load(const std::string filename, const std::vector<long>& initialMemory);
    STATUS run();
    std::vector<long> getDataMem();
    STATUS reset();
};

GritVM.cpp

#include "GritVM.hpp"

GritVM::GritVM() : accumulator(0), machineStatus(WAITING) { }/*Default constructor*/

/*Resets the machine state to default*/
STATUS GritVM::reset() { 
    accumulator = 0;
    machineStatus = WAITING;
    //dataMem.clear();
    myDataMem.clear(); /**>>>>>HERE<<<<<**/
    instructMem.clear();
    return machineStatus;
}

/*Returns the current data in the Data Memory*/ /**>>>>>HERE<<<<<**/
std::vector<long> GritVM::getDataMem() {
    //return dataMem;
    return myDataMem.tempVec_to_stlVec(myDataMem);
}

STATUS GritVM::load(const std::string filename, const std::vector<long>& initialMemory) {

    /**Taken away some reading from gvm file to save room***/

    /*Copy the memory to data vector*/
    //dataMem = initialMemory;
    myDataMem= initialMemory; /**>>>>>HERE<<<<<**/

    return machineStatus;
}

/*Run instruction for the Grit machine*/
STATUS GritVM::run() {

    /***Taken away to save room, is not related to dataMem vector***/
    return machineStatus;
}

/*All these evaluate came from the table in the book */
long GritVM::evaluate(Instruction current_instruction) {

    long move_instruction_amount = 0; /*Instruction move counter*/

    /*******SOME OF THE dataMem are here*******/

    switch (current_instruction.operation) {
    case AT: 
        machineStatus = RUNNING;
        move_instruction_amount = 1;
        //accumulator = dataMem.at(current_instruction.argument);
        accumulator = myDataMem.at(current_instruction.argument);
        break; /**>>>>>HERE<<<<<**/
    case SET:
        machineStatus = RUNNING;
        move_instruction_amount = 1;
        //dataMem.at(current_instruction.argument) = accumulator;
        myDataMem.at(current_instruction.argument) = accumulator;
        break; /**>>>>>HERE<<<<<**/
    case INSERT:
        machineStatus = RUNNING;
        move_instruction_amount = 1;
        //dataMem.insert(current_instruction.argument, accumulator);
        myDataMem.insert(current_instruction.argument, accumulator);
        break; /**>>>>>HERE<<<<<**/

         /***a lot of cases are taken out***/
    default:
        machineStatus = ERRORED; 
        break;
    }

    return move_instruction_amount;
}

/*Takes the instruction, and advancces its amount, given from the pdf file*/
void  GritVM::advance(long move_instruction_amount) {

    /***taken away to save room, doesn't use dataMem vector****/
}

1 Ответ

1 голос
/ 07 июня 2019

Прежде всего, я бы порекомендовал не реализовывать свой собственный вектор. Здесь много подводных камней, и сложно сделать это правильно.


Существует много проблем, препятствующих конвертации.

Во-первых, ваш operator= получает изменяемую ссылку на вектор:

//    not const  -------v
ArrayVector& operator= (std::vector<Object>& stlv){
    ArrayVector copy = stlv;
    std::swap(*this, copy);
    return *this;
}

//          v------- not const either
ArrayVector(std::vector<Object>& stl_vector_para){ 
   Arr = stl_vector_para;
   capacity = stl_vector_para.capacity();
   num_longElem = stl_vector_para.size();
}

Используются изменяемые ссылки, но вам не нужно фактически изменять вектор. Создание их const исправит первую проблему, так как вы пытаетесь передать ему вектор const:

//     a reference to a const vector ---v
STATUS load(const std::string filename, const std::vector<long>& initialMemory) {
    myDataMem = initialMemory;
    //          ^----- cannot pass a const vector to a
    //                 function that takes a mutable one

    return machineStatus;
}

Тогда у вас есть проблема на всю жизнь:

// returns by reference
std::vector<Object>& tempVec_to_stlVec(ArrayVector& av) {
    // to_stdVec lives until the end of the function
    std::vector<Object> to_stdVec = av;
    return to_stdVec; // return a reference to an object that will die
}

Локальные переменные не живут за пределами своих областей. Вы возвращаете ссылку на мертвый вектор. Вместо этого просто верните значение:

// by value
std::vector<Object> tempVec_to_stlVec(ArrayVector& av) {
    // to_stdVec lives until the end of the function
    std::vector<Object> to_stdVec = av;
    return to_stdVec; // return the object by value
}

Оптимизация возвращаемого значения позаботится об эффективности возврата. Если эта оптимизация не может быть выполнена, конструктор перемещения позаботится об этом.


Потом я увидел ошибки, которых не было в опубликованных ошибках.

Векторы не конвертируются в указатели:

Arr = stl_vector_para;

Так не работает. Если вы действительно хотите создать свой собственный векторный класс, вы должны выполнить динамическое распределение и скопировать данные вручную.

C ++ предлагает такую ​​структуру данных по одной причине: чтобы сделать нашу жизнь проще и сделать C ++ приятным. Реализация вашего собственного вектора - это обычно боль, если вы не знаете, что делаете.

...