-3

I am continually writing something akin to

std::vector< std::vector< double > > A(N, std::vector< double >(M));

and I would like to replace this with something like

matrix A(N,M);

by using a #define directive. I've looked at #define directives and think I can create a function like matrix(A,N,M) that would declare a vector of vectors as follows:

#define matrix(A, N, M) std::vector< std::vector< double > > A(N, std::vector< double >(M))

but I would rather not declare my matrices as matrix(A,N,M), but rather matrix A(N,M). My question is - how do I use the #define directives to account for changing a variable name?

drjrm3
  • 4,474
  • 10
  • 53
  • 91
  • 1
    Using nested `vector`s as a matrix is a bad idea to begin with. Implement a proper matrix class or use an existing one. Either way, stop those useless macro hacks. – Baum mit Augen Jul 05 '17 at 01:53
  • 3
    Also, looking at this question, you should most certainly read a good C++ book. – Baum mit Augen Jul 05 '17 at 01:53
  • @BaummitAugen Thanks for your feedback. I have read many C++ books actually. I'm using a vector of vectors right now to implement the math ASAP. Once I have validated the math I will go back and restructure with a 'proper' matrix class as you suggested. Either way, none of your comments so far answer the question. – drjrm3 Jul 05 '17 at 02:03
  • 3
    If the comments were supposed to answer the question, I would have posted them as an answer. They are, however, just comments. And for testing some math stuff, there are enough linear algebra libraries readily available that properly implement matrix math. – Baum mit Augen Jul 05 '17 at 02:06
  • @BaummitAugen matrices are just miserable corner cases of vectors of vectors for miserable people :D – iehrlich Jul 05 '17 at 02:11
  • @BaummitAugen Such as blas, lapack, eigen, cublas, etc. I'm well aware. For now, however, I am writing it from scratch as it is by far the fastest way for me to get preliminary results. – drjrm3 Jul 05 '17 at 02:12
  • Are `N` and `M` constant expressions in your use case? – rici Jul 05 '17 at 02:35
  • @rici yes, they are. – drjrm3 Jul 05 '17 at 02:55
  • In that case, have you considered `template using Matrix = std::array, N>;`? That would let you write `Matrix A;`, which is not quite what you asked for but it's still quite tidy. http://coliru.stacked-crooked.com/a/1b63279ac555a7a6 – rici Jul 05 '17 at 03:25

2 Answers2

1

You can use typedef and define type, something like that:

#include <vector>
using namespace std;

int main() 
{
    int N = 10;
    typedef std::vector< std::vector<double> matrix;
    matrix  A(N, std::vector< double >(N));
    return 0;

}

or more safety (if you don't know, that matrix will be right)

int main()
{
    int N = 10;

    typedef std::vector< std::array<double, 5> > matrix;
    matrix  A(N, std::array< double , 5 >());
    return 0;
}

my wrapper for matrix with vectors

#include <iostream>
#include <vector>
#include <exception>
#include <algorithm>

template< typename T >
class WrapperMatrix
{
public:
    WrapperMatrix(const int& weight, const int& length);
    void pushLine(const std::vector<T>&&);
    void pushColumn(const std::vector<T>&&);
    void display();
private:
    std::vector<std::vector<T>> matrix;
};
template<typename T>
WrapperMatrix<T>::WrapperMatrix(const int& weight, const int& length) 
{
    this->matrix = std::vector<std::vector<T>>(weight, std::vector<T>(length));
}

template <typename T>
void WrapperMatrix<T>::pushLine(const std::vector<T>&& newLine)
{
    if (newLine.size() == this->matrix.at(0).size())
        matrix.emplace_back(std::move(newLine));
    else
        throw std::invalid_argument("Invalis syntax");
}
template <typename T>
void WrapperMatrix<T>::pushColumn(const std::vector<T>&& newColumn)
{
    if (newColumn.size() == this->matrix.size())
    {
        for (int i = 0; i < matrix.size(); ++i)
            matrix.at(i).emplace_back(std::move(newColumn.at(i)));
    }
    else
        throw std::invalid_argument("Invalid syntax");
}
template<typename T>
void WrapperMatrix<T>::display()
{
    for (int i = 0; i < matrix.size(); ++i)
    {
        for (int j = 0; j < matrix.at(0).size(); ++j)
            std::cout << matrix.at(i).at(j);
        std::cout << std::endl;
    }
}
int main()
{
    std::vector<int> v1{ 1,2,3,4,5 };
    std::vector<int> v2{ 1,2,3,4,5,6 };
    std::vector<int> v3{ 2,3,4,5,6 };

    WrapperMatrix<int> vw(5,5);
    try {
        vw.pushLine(std::move(v1));
        vw.pushColumn(std::move(v2));
        //vw.pushLine(std::move(v3));
    }
    catch (const std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }

    vw.display();
    return 0;
}
21koizyd
  • 1,843
  • 12
  • 25
  • 1
    No, a vector of vectors does not properly implement a matrix. – Baum mit Augen Jul 05 '17 at 01:59
  • 1
    Thanks. `typedef` is a much better idea and I'm surprised I didn't think of it first! Either way, it doesn't solve the issue of wanting to allocate on declaration. – drjrm3 Jul 05 '17 at 01:59
  • @BaummitAugen question was deffrent, not about how create vector of vectors. I only show how define complexity type – 21koizyd Jul 05 '17 at 02:00
  • @21koizyd I'm not saying you are technically incorrect, just saying this answer is not useful as it fails to address key issues in the code in the question. Thus my downvote. – Baum mit Augen Jul 05 '17 at 02:02
  • 1
    @BaummitAugen why not like this I see the same solution in e.g https://stackoverflow.com/questions/12375591/vector-of-vectors-to-create-matrix – 21koizyd Jul 05 '17 at 02:07
  • @21koizyd So other people had the same poor idea before. What's your point? – Baum mit Augen Jul 05 '17 at 02:08
  • no, I ask why? So i check and display vector right. – 21koizyd Jul 05 '17 at 02:13
  • 2
    @21koizyd The inner vectors don't even have to have all the same length. A matrix and a sequence of sequences are completely different data structures, the fact that one can access their elements with a similar syntax does not change that. – Baum mit Augen Jul 05 '17 at 02:17
  • It's not about being symmetrical. `{{0,1},{2}}` would be a valid `vector>`, but no a valid matrix. They are just different things. – Baum mit Augen Jul 05 '17 at 02:24
  • @BaummitAugen okey I understand what you mean. – 21koizyd Jul 05 '17 at 02:24
  • @BaummitAugen now, second version is save, I'm right? – 21koizyd Jul 05 '17 at 02:32
  • It's somewhat better, at least it guarantees some sort of matrix shape. I'll remove my downvote. – Baum mit Augen Jul 05 '17 at 02:34
0

Alternative answer to typedef

using matrix = std::vector< std::vector<double>>;

This form can be more readable, especially with function and array types. E.g. using arr10 = Foo[10] is clearer than typedef Foo arra10[10]. The = sign clearly separates what's being defined and how it's defined.

(Ignoring the whole "matrix is not a vector of vectors" discussion)

MSalters
  • 173,980
  • 10
  • 155
  • 350