Search code examples
c++visual-c++queueg++comparator

How to fix an error associating with a comparator?


The code is compiled, and run without any issue in CLion IDE with g++ compiler in MinGW, however, the same exact code has a compilation error in Visual Studio IDE and with (MSVC compiler)

I believe the error should have to do with the follwoing comparator class:

struct CompareVertices {
    inline bool operator()(shared_ptr<Vertex> a, shared_ptr<Vertex> b) const {
        return a->get_distance() < b->get_distance() ? false : true;
    }
};

which later has been made use of in:

 priority_queue<shared_ptr<Vertex>, vector<shared_ptr<Vertex>>, CompareVertices> pQ;

I get the following error (Only in VS 2019 (MSVC) and no error in Clion(MinGW)):

File: C:\Program Files (x86)\Microsoft Visual 
Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\xutility
Line: 1520
Expression: invalid comparator

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\kernel.appcore.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\msvcrt.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\rpcrt4.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\user32.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\win32u.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\gdi32.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\gdi32full.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\msvcp_win.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\ucrtbase.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\imm32.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\TextShaping.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\uxtheme.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\combase.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\msctf.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\oleaut32.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\sechost.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\bcryptprimitives.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\TextInputFramework.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\CoreMessaging.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\CoreUIComponents.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\SHCore.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\ws2_32.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\ntmarta.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\advapi32.dll'. 
'practice_Classes.exe' (Win32): Loaded 'C:\Windows\System32\WinTypes.dll'. 

Network.h

using namespace std;
typedef long double ld;
class Arc; // forward declaration

class Vertex {

private:
    string name_{ "" };
    long double dist_{ numeric_limits<long double>::infinity() }; 
    shared_ptr<Vertex> prev_{ nullptr };
    bool visited_{ false };
    vector<shared_ptr<Vertex>> adjacent_vertices_;
    vector<shared_ptr<Arc>> adjacent_arcs_;

public:

    Vertex() = default;
    Vertex(string name) : name_(name)
    {
    }
    ~Vertex() = default;


    Vertex(const Vertex& cpyObj) :
        name_(cpyObj.name_),
        dist_(cpyObj.dist_),
        visited_(cpyObj.visited_),
        adjacent_vertices_(cpyObj.adjacent_vertices_),
        adjacent_arcs_(cpyObj.adjacent_arcs_)
    {
        prev_ = make_shared<Vertex>(name_);
    }

    Vertex(Vertex&& moveObj) noexcept :
        name_(move(moveObj.name_)),
        dist_(move(moveObj.dist_)),
        prev_(move(moveObj.prev_)),
        visited_(move(moveObj.visited_)),
        adjacent_vertices_(move(moveObj.adjacent_vertices_)),
        adjacent_arcs_(move(moveObj.adjacent_arcs_))
    {
        moveObj.prev_ = nullptr;
    }


    // some setter and getter functions  including the follwoing two:
    inline void set_prev(shared_ptr<Vertex> ptr) { this->prev_ = ptr; }
    inline auto get_prev() const { return prev_; }
   
};

then:

struct CompareVertices {
    bool operator()(shared_ptr<Vertex> a, shared_ptr<Vertex> b) const {
        return a->get_distance() < b->get_distance() ? false : true;
    }
};


class Arc {

private:
    shared_ptr<Vertex> from_{ nullptr };
    shared_ptr<Vertex> to_{ nullptr };
    long double arc_length_{ 0 };

public:

Arc() = default;
Arc(shared_ptr<Vertex> from, shared_ptr<Vertex> to, long double length) : arc_length_(length)
{
    this->from_ = from;
    this->to_ = to;
}
~Arc() = default;

// some setter and getter and output stream functions here   
};

class Network {

private:

    vector<shared_ptr<Vertex>> Vertices_;
    vector<shared_ptr<Arc>> Arcs_;

public:

    Network() = default;
    Network(vector<shared_ptr<Vertex>>& Vertices, vector<shared_ptr<Arc>>& Arcs) : Vertices_(Vertices), Arcs_(Arcs) {}
    ~Network() = default;

// also some setter and getter plus some other utility functions here

};



class Dijkstras_Alg
{
private:
    shared_ptr<Vertex> source_node_{ nullptr };
    shared_ptr<Vertex> destin_node_{ nullptr };
    shared_ptr<Network> Ntwk_{ nullptr };

public:

    Dijkstras_Alg() = default;
    Dijkstras_Alg(shared_ptr<Vertex> src, shared_ptr<Vertex> destin, shared_ptr<Network> Ntwk) {
        cout << "Dijkstra construction running\n";
        this->source_node_ = src;
        this->destin_node_ = destin;
        this->Ntwk_ = Ntwk;
    }
    ~Dijkstras_Alg() = default;

// some setter and getter and utility functions here 

    void compute_path() {
        std::priority_queue< std::shared_ptr<Vertex>, std::vector<shared_ptr<Vertex> >, CompareVertices > pQ;
        source_node_->set_distance(0);
        pQ.push(source_node_);
        while (!pQ.empty())
        {
                    // arcs relaxation is done here
                pQ.pop();
                current_vertex->set_visited();
            }
    
        }  
    };

enter image description here

enter image description here

this is printed: Dijkstra construction running, and then the error is popping up!

Any workaround?

PS:

  1. it is not due to "inline" keyword
  2. the program works perfectly in CLion with g++ compiler (with or without the copy constructor and move constructor)

Solution

  • Your somewhat odd comparator...

    return a->get_distance() < b->get_distance() ? false : true;
    

    is effectively this:

    return a->get_distance() >= b->get_distance();
    

    The problem is that >=, and specifically the equivalence inclusion of that operation. That does not enforce a strict-weak ordering. Equivalence should not be a part of any strict weak order comparator. That is left to the algorithm utilizing the comparator to determine by derivation, specifically when neither (a<b) nor (b<a) are true, the objects are considered equivalent.

    Therefore, the comparator you should be using is simple this:

    return b->get_distance() < a->get_distance();
    

    That should provide the ordering you seem to want.