lundi 17 février 2020

I have a vector that has pointers to elements from 2 subtypes accessed via an interface. Can't seem to re-arrange the vector

I'm working on a really over engineered matrix calculator for school and hit a brick wall with the very last function I need. The full version of the transpose() is supposed to re-arrange my matrix and to switch collumns and rows around.

I posted this question earlier with a snippet but was asked to write a minimum reproducable sample. This isn't very "minimum" but I tried.

So. I have a std::vector<std::unique_ptr<Interface>> that can hold objects of types Sub1 and Sub2.

In the full version I have a class that bypasses Interface and works fine since it only holds Sub2 objects.

However I can't seem to get it to work when there are multiple types in the vector. Nothing I've tried in the past few hours has done anything.

#include <iostream>
#include "main.h"
#include <memory>
#include <utility>
#include <vector>
#include <sstream>


//this is the one that won't work
Super Super::transpose() const {
    Super newMatrix = *this;
    int i = 1;
    for(auto& elem : elements){
        *elem = *newMatrix.elements[i];
        i--;
    }
return *this;
}


int main() {
    std::vector<std::unique_ptr<Interface>> newMatrix;
    newMatrix.push_back(std::unique_ptr<Sub1>(new Sub1('x')));
    newMatrix.push_back(std::unique_ptr<Sub2>(new Sub2(1)));
    Super mtx(std::move(newMatrix),2 );
    std::cout << mtx << std::endl;
    mtx.transpose();
    std::cout << mtx;
    return 0;
}

//busywork from here on 
Super::Super(std::vector<std::unique_ptr<Interface>> matrix, int pN){
    elements = std::move(matrix);
    n = pN;
}

std::unique_ptr<Interface> Sub1::clone() const {
    char newVal = val;
    return std::unique_ptr<Sub1>(new Sub1(newVal));
}

std::unique_ptr<Interface> Sub2::clone() const {
    int newVal = i;
    return std::unique_ptr<Sub2>(new Sub2(newVal));
}

Sub1::Sub1(char pVal) {
    val = pVal;
}

Sub2::Sub2(int pI) {
    i = pI;
}

std::string Sub1::toString() const {
    std::stringstream ss;
    ss << val;
    return ss.str();
}

std::string Sub2::toString() const {
    std::stringstream ss;
    ss << i;
    return ss.str();
}

std::ostream &operator<<(std::ostream &os, const Super &matrix) {
    os << "[";
    int i = 0;
    for (auto &elem : matrix.elements) {
        os << elem->toString();
        if (i < matrix.n - 1) {
            os << ",";
        }
        i++;
    }
    os << "]";
    return os;
}

Super::Super(const Super &matrix) {
    n = matrix.n;
    for (auto &elem : matrix.elements) {
        std::unique_ptr<Interface> newElem = elem->clone();
        elements.push_back(std::move(newElem));
    }
}

And heres the header

#ifndef EXAMPLE_MAIN_H
#define EXAMPLE_MAIN_H

#include <memory>
#include <vector>


class Interface{
public:
    virtual ~Interface() = default;
    virtual std::unique_ptr<Interface> clone() const = 0;
    virtual std::string toString() const = 0;
};

class Super{
private:
    std::vector<std::unique_ptr<Interface>> elements;
    int n = 2;
public:
    Super(std::vector<std::unique_ptr<Interface>> elements, int n);
    Super(const Super &matrix);
    Super transpose() const;
    friend std::ostream &operator<<(std::ostream &os, const Super &matrix);
};

class Sub1: public Interface{
private:
    char val;
public:
    Sub1(char pVal);
    std::string toString() const override;
    std::unique_ptr<Interface> clone() const override;
};


class Sub2: public Interface{
private:
    int i;
public:
    Sub2(int pI);
    std::string toString() const override;
    std::unique_ptr<Interface> clone() const override;
};


std::ostream &operator<<(std::ostream &os, const Super &matrix);

#endif //EXAMPLE_MAIN_H

Aucun commentaire:

Enregistrer un commentaire