0

I'm trying to make an array of pairs of vectors, and in the vectors is another pair of int and float. Here is the code to help explain: pair<vector<pair<int,float> >, vector<float> >[numNodes];

At first I just had an array of a vector of pairs, but now that I changed it to an array of pairs I'm being thrown errors. I think the errors have to do with the placement of make_pair but I'm not sure.

Here is my code, but first, I little more information on what exactly I'm trying to do with the code. I'm working on a school assignment where the goal is to read in a three files of a graph and store it as an adjacency matrix and adjacency list. Right now I'm working on the list. One file has just the connections, another has the weights of the connections, and the last file has the position values of each node. Then I will search the graphs with different search algorithms. The array of vectors was the adjacency list and all the other data types involved in the pair<vector<pair<int,float> >, vector<float> >[numNodes]; were an attempt to store these variables in the list. I know another way of doing this would be to have a Node object with member variables where I can save the nodeID and position values, but I don't know exactly how this would work in terms of adding it into the list. Also would there be advantages to doing this rather than having everything stored in the list?

class AdjacencyList{

public:
    pair<vector<pair<int,float> >, vector<float> > *adjList;
    int numNodes;

    AdjacencyList(int numNodes){//constructor
        this->numNodes = numNodes;

        adjList = new pair<vector<pair<int,float> >, vector<float> >[numNodes];
    }

    void addEdge(int sourceNode, int destNode, float weight, vector<float> posVals){
        make_pair(adjList[sourceNode].push_back(make_pair(destNode, weight)), posVals);
    }
}



And here is the error I'm being thrown:

main.cpp:71:39: error: no member named 'push_back' in

      'std::__1::pair<std::__1::vector<std::__1::pair<int, float>,
      std::__1::allocator<std::__1::pair<int, float> > >,
      std::__1::vector<float, std::__1::allocator<float> > >'
        make_pair(adjList[sourceNode].push_back(make_pair(destNode, weig...



Another Error I'm getting after changing the array of vectors to an array of pairs is this:

no member named 'size' in

      'std::__1::pair<std::__1::vector<std::__1::pair<int, float>,
      std::__1::allocator<std::__1::pair<int, float> > >,
      std::__1::vector<float, std::__1::allocator<float> > >'
        return adjList->size();



This size function was working before the change, which makes me think these errors are happening because its recognizing it as a pair now instead of an array. Any ideas on how to fix this?

  • your `adjList` is a `pair`. Look at the extreme left on the declaration. At the end it is a `pair` whatever is going on is inside that `pair`. Edit your question and add more information about what is the data you are storing in the `adjList`. I think you have interchanged the first `vector` inside of the `pair` with it e.g. you might be looking for `vector` which seems logical for a adjacency list. – abdullahQureshee Oct 04 '20 at 06:44
  • You must not use raw pointers and ````new```` for owned memory. Use a ````std::vector```` instead. The result of ````adjList[sourceNode].```` is a ````std::pair````. A ````std::pair```` does not have a ````push_back```` function. And the result of ````std::make_pair```` in your "addEdgeFunction" is never used. In my opinion, the structure of your data is wrong. If you edit your question and explain in detail WHAT you want to do, then I will prepare an answer and show you HOW to do – A M Oct 04 '20 at 06:45
  • 1
    If you use so many `std::vector`, why do you use a `*adjList;` raw pointer? Just use a vector? – KamilCuk Oct 04 '20 at 07:12
  • 1
    You code would be so much easier to understand if you wrote your own classes instead of vector of pair of vector of etc... You've taken that to such an extreme that it's getting a bit ridiculous. Any code that nests more than one level of standard classes has gone a bit too far IMHO. Even using a few typedefs would help. Using meaningful names is the most important way to make code comprehensible. Don't underestimate the benefits of making your code understandable, even if it's only to yourself. – john Oct 04 '20 at 07:47
  • This sounds like an [X-Y problem](http://xyproblem.info/). Why don't you tell us what you want to achieve, instead of asking us to help fix your own solution. You might be on the wrong track... – JHBonarius Oct 04 '20 at 11:58

2 Answers2

0

I have no idea what vector of pairs of vectors of pairs of ints and floats and vectors of floats could possibly in any possible way represent, but anyway you could just assign to the pairs of vectors you want to assign to:

#include <vector>

class AdjacencyList{

public:
    std::vector<
        std::pair<
            std::vector<std::pair<int,float>>,
            std::vector<float>
        >
    > adjList;
    int numNodes;

    AdjacencyList(int numNodes) :
        numNodes(numNodes),
        // construct the vector with numNodes default-constructred elements
        adjList(numNodes) {
    }

    void addEdge(int sourceNode, int destNode, float weight, std::vector<float> posVals){
        // prefer at() instead of [] for error checking
        adjList.at(sourceNode) = std::make_pair(
            std::vector<std::pair<int, float>>{
                // vector of pairs?? anyway:
                std::make_pair(
                    destNode, weight
                )
            },
            posVals
        );
    }
};

Do not use raw pointers - use std::vector for managing dynamic array. Your code leaks memory allocated by new.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
0

In the first error thrown, the compiler is complaining about a missing method push_back being called. If you look at it, this makes sense because you are trying to call push_back from a pair variable (which does not have implemented any push_back method). And a similar thing goes with the second error: size() is a valid method for the vector class, but here you are calling it from a pointer pointing to an array (check this question for more info).

Instead of an array of pairs, you could use a vector of pairs, or even a set of pairs:

class AdjacencyList{

public:
    vector<pair<vector<pair<int,float> >, vector<float> > > adjList;
    int numNodes;

    AdjacencyList(int numNodes){//constructor
        this->numNodes = numNodes;

        // no need to initialize the vector
        //adjList = new pair<vector<pair<int,float> >, vector<float> >[numNodes];
    }

    void addEdge(int sourceNode, int destNode, float weight, vector<float> posVals){
        // add the new pair <int, float> to the existent vector for this source node
        adjList[sourceNode].first.push_back(make_pair(destNode, weight));

        // define second value of the outer pair as the parameter variable posVals?
        adjList[sourceNode].second = posVals;

        // or you wanted to do this? I don't think so :S
        make_pair(adjList[sourceNode].first, posVals);
    }
}

You could do the same using an outer set instead of vector, and then you would need to change the push_back(...) for insert(...), so that you obtain the benefits of sets of pairs as well.

Actually, if you need to do it using outer arrays, then your code would be fine but changing your AddEdge function to the one proposed above.

I don't really know which is the desired performance of the code, but if you provide more information about it I might be able to help a bit more.

I think you have some inconsistencies in the type declared and the type being added. You have declared an array (now does not matter whether it is an array, vector, or set) of pairs of vectors. Whereas on your addEdge function you are creating a pair of None (push_back returns None) and vector. The push_back on its side is adding the pair <int, float> of the first vector of the outer pair to you differently variable defined above.

Dharman
  • 30,962
  • 25
  • 85
  • 135