0

This is my attempt at passing a N-D vector of arbitrary element types, inner and outer lengths to a class and printing its contents. I know there are a few issues but I have not been able to resolve. How would I assign the arbitrary inner vector length to a variable or set of variables? I have attempted to pass iterators to the constructor and assign them to member variables (with and without passing the vector) but that has not been successful. I understand there are libraries for handling matrix objects and other questions which address problems similar to the one posed herein, however, there are unique/fringe scenarios which comprise the motivation for this question.

#include <iostream>
#include <iterator>
#include <vector>

template <typename V, typename I>
class myVec{
    private:
        I rows;
        I cols;
        std::vector< std::vector<V> > vec( rows , vector<int> (cols));

    public:
        myVec(std::vector< std::vector<V> > const &myArr){
            vec = myArr;
            rows = myArr.size();
            cols = myArr[].size();
        }
        void printVec(){
            for(int i = 0; i < vec.size(); i++){
                std::cout << "{";
                for(int j = 0; j < vec[i].size(); j++){
                    std::cout << vec[i][j];
                }
                if (i < vec.size()){ 
                    std::cout << "}";
                    if (i < vec.size()-1){
                        std::cout << ",";
                        std::cout << " ";
                    }
                }
            }
            std::cout << std::endl;
        }
};

int main () {
    std::vector< std::vector<int> > mainVec = {{1, 2, 4}, {5, 6, 7, 8}, {4, 3, 2, 1, 7}, {8, 7, 6, 5, 9, 3}};
    myVec<int, int> vec1 = myVec<int, int>(mainVec); 
    vec1.printVec();
    return 0;


Darnoc Eloc
  • 75
  • 11
  • 1
    With `typename I`, initialization `vec( I , vector (I));` doesn't make sense. You use a _type_ where an _expression_ (e.g. a value) is expected. Why not just `std::vector< std::vector > vec;`? – Scheff's Cat Feb 26 '20 at 08:25
  • 1
    Do you need to write you own implementation, or do you need efficient way to work with 2-D vectors? In latter case I would recommend to look at Eigen. – sklott Feb 26 '20 at 08:28
  • 2
    Does this answer your question? [A proper way to create a matrix in c++](https://stackoverflow.com/questions/618511/a-proper-way-to-create-a-matrix-in-c) – Scheff's Cat Feb 26 '20 at 08:30
  • 1
    FYI: [SO: C++ Matrix Class](https://stackoverflow.com/q/2076624/7478597) – Scheff's Cat Feb 26 '20 at 08:31
  • It looks like you intended for `I` to be a number, not a type. What's the point in parameterizing the type of `cols` and `rows`? – molbdnilo Feb 26 '20 at 08:42
  • 1
    What is `cols` going to be used for when you have a different number of columns in each row? – Ted Lyngmo Feb 26 '20 at 08:43
  • The type of vector elements does not have to be int, I assumed there’s a way to account for the varying size of each column (with an iterator?). – Darnoc Eloc Feb 26 '20 at 08:55
  • The armadillo library seems to be a good solution but I want to design my own to acquire a better grasp of the fundamentals. – Darnoc Eloc Feb 26 '20 at 09:41
  • 1
    @DarnocEloc I don't have time to finalize a proper answer but perhaps you can get some ideas out of [this](https://godbolt.org/z/2xHBpe). – Ted Lyngmo Feb 26 '20 at 10:06
  • if(auto cit = row.begin(); cit != row.end()), I understand this syntax was incorporated to allow for more compact code and to prevent leakage into ambient scope, but what are the cons (apart from backward compiler compatibility)? – Darnoc Eloc Feb 26 '20 at 12:02
  • You prevent it by just moving it out, before the `if`, like [so](https://godbolt.org/z/yXwcht) - or by using C++17 instead. There are no cons. It narrows the scope for the variable - which is a good thing. – Ted Lyngmo Feb 26 '20 at 12:14
  • @DarnocEloc One thing at a time please. I realize that I dumped code on you without much of an explanation because I was in a hurry (but I did it with good intent). Is the original question you asked still open so to speak? If so, can you clarify (by editing it) what you need help with (within what's reasonable given the original question)? I recommend that you do not put additional questions in - especially not questions regarding recommendations about libraries etc. – Ted Lyngmo Feb 26 '20 at 22:38

1 Answers1

0

Basic solution that utilizes iterators as previously suggested for the print method. The vector is passed by const ref, how much of an advantage is there to using move assign instead? Index operator overloads and access methods are not included at this time, plan to include exception handling for out of bounds and other cases.

#include <iostream>
#include <vector>

template <typename V>
class myVec{
    private:
        std::vector< std::vector<V> > vec;

    public:
        myVec();
        explicit myVec(const std::vector< std::vector<V> > &myArr):vec(myArr) {};
        explicit myVec(std::vector< std::vector<V> > &&myArr):vec(std::move(myArr)) {};
        }
        void printVec(){
            std::cout << '{';
            for(auto& row:vec){
                if(&row != &vec.front()) std::cout << ", "; 
                std::cout << '{';
                if(auto cln = row.begin(); cln != row.end()) {
                    std::cout << *cln;
                    for(++cln; cln != row.end(); ++cln) std::cout << ", " << *cln;
                }
                std::cout << '}';
            }
            std::cout << '}' << std::endl;
        }
};

int main () {
    std::vector< std::vector<int> > mainVec = {{1, 2, 4}, {5, 6, 7, 8}, {4, 3, 2, 1, 7}, {8, 7, 6, 5, 9, 3}};
    myVec<int, int> vec1 = myVec<int, int>(mainVec); 
    vec1.printVec();
    return 0;
Darnoc Eloc
  • 75
  • 11
  • It looks somewhat like what I suggested, but yet a lot different. What made you reintroduce the template parameter `I` and why do you think it's capable of storing the value that `vector<>.size()` returns? Why did you move initialization out of the member initialization list? It will make your container unsuitable for types that can not be default constructed and also less efficient in general. Why use string literals instead of character literals? Why save `row` in the first place? You have a first class container (`vec`) that knows exactly what it contains. – Ted Lyngmo Feb 27 '20 at 00:11
  • You also use some member functions that I proposed and implemented - but this answer does not. – Ted Lyngmo Feb 27 '20 at 00:14
  • Why would the container be unsuitable for types that cannot be default constructed without use of member initialization list? – Darnoc Eloc Feb 27 '20 at 03:16
  • Yes, a type like `struct Foo { Foo() = delete; Foo(int); };` would not be considered and cause compilation error. – Ted Lyngmo Feb 27 '20 at 03:50
  • So initializer list triggers parameterized constructor call, limits redundant constructor calls and initialization/assignment of members while explicit restricts signature (parameter) of constructor call, enforcing type compatibility between argument and object. – Darnoc Eloc Feb 27 '20 at 04:26
  • Is that a question or a paragraph in a book? Oh, wait, I don't want to know. Ask a new question and people a lot more skilled than me will answer it. – Ted Lyngmo Feb 27 '20 at 04:32
  • Thanks, I appreciate the insight and suggestions, just describing my interpretation of the advantages to use of initializer list and explicit specifier. – Darnoc Eloc Feb 27 '20 at 06:11