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:
"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 within 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 ?
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;
};