Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Issue with std::set::insert using a custom comparator

I wrote a small struct used to sort dependencies between projects (it could be used to sort anything really, the interface used is just a std::string) in a container/solution.

The dependencies are defined and fed from a json object (parsing is done using boost::json).

Example dependencies:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

"container_dependency_tree": {
    "abc": ["def","hello","world"],
    "def": ["xyz","x","y"],
    "xyz": [],
},

Header:

#pragma once

#include <boost/json.hpp>
#include <map>
#include <string>
#include <vector>
#include <set>

namespace tmake {

    struct container_dependency_tree_t {
    private:

        std::map<std::string, std::vector<std::string>>
            m_flat;

        bool
            m_compare(const std::string& lhs, const std::string& rhs) const;//returns true if lhs depends on rhs

        std::set<std::string, decltype(&m_compare)>
            m_sorted = decltype(m_sorted)(&container_dependency_tree_t::m_compare);

    public:

        container_dependency_tree_t() {}

        container_dependency_tree_t(const boost::json::object& container_dependency_tree);

    public:

        const decltype(m_flat)&
            flat() const;

        const decltype(m_sorted)&
            sorted() const;
    };
}

Implementation:

#include <tmake/container_dependency_tree_t.h>

namespace tmake {

    container_dependency_tree_t::container_dependency_tree_t(const boost::json::object& container_dependency_tree) {
        for (const auto& kv : container_dependency_tree) {
            std::vector<std::string> dependencies;
            const boost::json::array& dd = kv.value().as_array();
            for (const auto& d : dd) {
                dependencies.push_back(d.as_string().c_str());
            }
            m_flat.emplace(kv.key(), dependencies);
        }

        for (const auto& f : m_flat) {
            m_sorted.insert(f.first);//***ISSUE HERE***
        }
    }

    bool container_dependency_tree_t::m_compare(const std::string& lhs, const std::string& rhs) const {
        auto find = m_flat.find(lhs);
        if (find == m_flat.end())
            return false;

        for (const auto& dependency : find->second) {
            if (rhs == dependency || m_compare(dependency, rhs)) {
                return true;
            }
        }

        return false;
    }

    const decltype(container_dependency_tree_t::m_flat)& container_dependency_tree_t::flat() const {
        return m_flat;
    }

    const decltype(container_dependency_tree_t::m_sorted)& container_dependency_tree_t::sorted() const {
        return m_sorted;
    }
}

The issue is with the instruction m_sorted.insert(f.first);.

I get thrown some compiler mumbo-jumbo that I dont understand – the error is somewhere withing the STL implementation files (MSVC xutility(1372,19): error C2064: le terme ne correspond pas Ă  une fonction qui prend 2 arguments).

What am I doing wrong ?

>Solution :

The error comes from you trying to use a class member function which has an implicit first parameter that is the this pointer. Since you need access to m_flat you need to wrap up the object to use with the function to call so that the set gets a function object that takes just two const string& parameters. You can do that like

struct container_dependency_tree_t {
private:

    std::map<std::string, std::vector<std::string>>
        m_flat;

    bool 
        m_compare(const std::string& lhs, const std::string& rhs) const;//returns true if lhs depends on rhs

    std::set<std::string, std::function<bool(const std::string&, const std::string&)>>
        m_sorted = decltype(m_sorted)([this](const std::string& lhs, const std::string& rhs)
                   { 
                       return this->m_compare(lhs, rhs); 
                   });

public:

    container_dependency_tree_t() {}

    container_dependency_tree_t(const boost::json::object& container_dependency_tree);

public:

    const decltype(m_flat)&
        flat() const;

    const decltype(m_sorted)&
        sorted() const;
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading