I run into a probles while trying to implement custom comparator support for my Heap data structure
Here's how I want it to look like:
template <class T, class Pred = std::less<T>>
class ConcurrentPriorityQueue {
private:
template <class T>
class Node
{
private:
T data;
bool operator < (const Node<T>& t) {
return Pred(data, t.data);
}
};
};
And this is a compare functor I want to use:
struct comp {
bool operator () (const std::pair<int, fn_type> &p1,
const std::pair<int, fn_type> &p2) const{
return p1.first < p2.first;
}
};
ConcurrentPriorityQueue<std::pair<int, fn_type>, comp> fqueue;
Everything looks pretty much right for me, however I get Error
Error 2 error C2661: 'ThreadPool::comp::comp' : no overloaded function takes 2 arguments c:\users\usr\documents\visual studio 2013\projects\secondtask\queue.hpp. Could you please help me out with this.
Pred refers to a type, not an instance of that type.
Currently you are trying to invoke a constructor of type Pred when doing Pred(data, t.data), you will first have to create an instance of Pred to be able to call a matching operator() (...) on it.
The below example creates a temporary instance of type Pred, and then calls its operator();
return Pred () (data, t.data); // 1) create a temporary instance of `Pred`
// 2) call its operator() with `data` and `t.data`
Related
Say I define a map with a custom comparator such as
struct Obj
{
int id;
std::string data;
std::vector<std::string> moreData;
};
struct Comparator
{
using is_transparent = std::true_type;
bool operator()(Obj const& obj1, Obj const& obj2) { return obj1.id < obj2.id; };
}
std::map<Obj,int,Comparator> compMap;
is there a good way to ensure that downstream users don't have to implement the comparator to use the map as a map?
for instance my compiler throws an error if I try to pass it to a function with a similar type.
template<class T>
inline void add(std::map<T, int>& theMap, T const & keyObj)
{
auto IT = theMap.find(keyObj);
if (IT != theMap.end())
IT->second++;
else
theMap[keyObj] = 1;
}
add(compMap,newObj); //type error here
EDIT:
I kinda over santitized this to make a generic case. and then overlooked the obvious
template<class T, class Comp, class Alloc>
inline void add(std::map<T, int, Comp, Alloc>& theMap, T const & keyObj)
still having issues with one use not being able to deduce T, but went from 80 erros to 1 so... progress
thanks everyone.
You can typedef the specialised type and use that type inplace of
std::map<...
typedef std::map<Obj,int,Comparator> compMap_t;
inline void add(compMap_t& theMap, Obj const & keyObj)
...
Downstream users either use the type declared by you
using my_important_map = std::map<Obj,int,Comparator>;
or better use functions which take a generic map type,
auto some_function(auto const& map_)
{
//do something with the map and don't care about the ordering
return map_.find(Obj(1));
}
I want to write a function that accepts a collection of type T, say std::vector<T>, but that does two different things depending on T. For example, if T is == comparable, then use a == b, else if T has a .value element, use that (a.value == b.value).
My first attempt was to use an overloaded function, but that fails if I pass in a derived class (subclass) of T.
Suppose, for example, I want to create an Exists method. (I know this can be implemented using std::find_if; it is an example only.) The following fails to compile:
using namespace std;
struct Base {
Base(string s) : value(std::move(s)) {}
string value;
};
struct Derived : public Base {
Derived(string s) : Base(std::move(s)) {}
};
bool Exists(const vector<string>& collection, const string& item) {
for (const auto& x : collection)
if (x == item)
return true;
return false;
}
bool Exists(const vector<Base>& collection, const Base& item) {
for (const auto& x : collection)
if (x.value == item.value)
return true;
return false;
}
This works fine for exact matches, such as:
Exists(vector<string>{"a", "b", "c"}, "b");
Exists(vector<Base>{{"a"}, {"b"}, {"c"}}, Base{"b"});
But it fails for derived classes:
Exists(vector<Derived>{{"a"}, {"b"}, {"c"}}, Derived{"b"})
The error is:
foo.cc:35:13: error: no matching function for call to 'Exists'
foo.cc:23:6: note: candidate function not viable: no known conversion from 'vector<Derived>' to 'const vector<Base>' for
1st argument
How can I solve this? I am interested in multiple answers, since each solution probably has pros and cons.
This is probably not a duplicate per se, but very close to this:
Is it possible to write a template to check for a function's existence?
My recommended approach is the more general solution implemented in that answer: use SFINAE.
The snippet of how to test for a member function is below (adapted from here):
template <class T>
class has_value {
template <class M>
static inline bool try_match(decltype(&M::value)) { }
template <class M>
static inline int try_match(...) { }
public:
static constexpr bool value =
sizeof(try_match<T>(nullptr)) == sizeof(bool);
};
this can then be combined with std::enable_if to solve your problem. I have posted a full solution as a GitHub gist.
In my opinion, this is superior to using base and inheritance checks as it works by simply checking (at compile-time) whether a given type has a given member. Additionally, it works for anything that has a type, meaning members, functions, static members / functions, types, etc.
One solution is to template the Exists() method and then have an overloaded comparison function. This only works if the type-specific code can be isolated. For example:
bool Equals(const string& a, const string& b) { return a == b; }
bool Equals(const Base& a, const Base& b) { return a.value == b.value; }
template <typename T>
bool Exists(const vector<T>& collection,
const typename vector<T>::value_type& item) {
for (const auto& x : collection)
if (Equals(x, item))
return true;
return false;
}
Pro: Probably the simplest solution.
Con: Does not work if you need to do some sort of expensive work up front. For example, if you need to call x.SomeExpensiveMethod() and you want to cache it for the item argument, this will not work.
Note that you need to use vector<t>::value_type and not just T in the argument or else you may get an error such as:
foo3.cc:30:13: error: no matching function for call to 'Exists'
cout << Exists(vector<string>{"a", "b", "c"}, "b") << endl;
^~~~~~
foo3.cc:21:6: note: candidate template ignored: deduced conflicting types for parameter 'T' ('std::basic_string<char>' vs.
'char [2]')
One solution is to use std::enable_if and std::is_base_of. For example:
template <typename T>
typename std::enable_if<std::is_base_of<Base, T>::value, bool>::type
Exists(const vector<T>& collection,
const typename vector<T>::value_type& item) {
const auto& item_cached = item.SomeExpensiveFunction();
for (const auto& x : collection)
if (x.SomeExpensiveFunction() == item_cached)
return true;
return false;
}
template <typename T>
typename std::enable_if<!std::is_base_of<Base, T>::value, bool>::type
Exists(const vector<T>& collection,
const typename vector<T>::value_type& item) {
for (const auto& x : collection)
if (x == item)
return true;
return false;
}
Pro: Much more general than overloading the Equals() function as described in another answer. In particular, the entire Exists() method can be customized per type.
Con: Much uglier, more complicated code.
I have a custom class Binary search Tree. I want to pass a comparator class as an argument (with default being std::less). Most of the answers I searched use the STL objects and then pass their custom comparators. I want something different.
// Tree class
template <class T,class Compare = less<T>>
class Tree
{
struct TreeNode
{
T data;
struct TreeNode * left;
struct TreeNode * right;
};
public:
void insert(T);
};
// Custom comparator class
template <class T>
class CustomCompare
{
public:
bool compare(const T&, const T &);
};
template<class T>
bool CustomCompare<T>::compare(const T & a, const T &b)
{
cout << "calling custom comparator";
return a<b;
}
// inserting in tree
template<class T,class Compare>
void Tree<T,Compare>::insert(T val)
{
// HOW DO I CALL COMPARE HERE? I tried this
if (compare(val->data , treeNode->data)) /// does not work.
// I get error - use of undeclared identifier compare.
//IF I DO THIS, I get error - expected unqualified id
Compare<T> x; // cannot create instance of Compare
// IF I DO THIS< I can create instance of Compare but cannot call function compare.
Compare x;
x.compare(....) -- Error no member named compare in std::less
}
I cannot make the CustomCompare::compare static as I want the code to work for std::less too.
I hope the question is clear.
Note: I know I can overload operator < for the classes that will be using it. I am preparing for the situation in case source code of those classes is not available
std::less has the following function to compare objects.
bool operator()( const T& lhs, const T& rhs ) const;
If you want to use a custom compare class to be an equal substitute, you have to have such a function in that class too.
Then, you would use it as:
if (compare()(val->data , treeNode->data))
I'm trying to remove a class object from list<boost::any> l
l.remove(class_type);
I tried writing something like this as a member function
bool operator == (const class_type &a) const //not sure about the arguments
{
//return bool value
}
How would you write an overload function to remove an object of class from a std::list of boost::any?
While your signature for operator== looks fine, overloading it for class_type isn't enough as boost::any doesn't magically use it. For removing elements however you can pass a predicate to remove_if, e.g.:
template<class T>
bool test_any(const boost::any& a, const T& to_test) {
const T* t = boost::any_cast<T>(&a);
return t && (*t == to_test);
}
std::list<boost::any> l = ...;
class_type to_test = ...;
l.remove_if(boost::bind(&test_any<class_type>, _1, to_test));
I'm building a series of predicates that duplicate lots of code, and so are being changed into a single template function class based on the std::unary_function. The idea is that my class interface requires methods such as Element_t Element() and std::string Name() to be defined, so the predicate template arguments are the object type and a value type to which comparison will be made as follows:
// generic predicate for comparing an attribute of object pointers to a specified test value
template <class U, typename R>
class mem_fun_eq : public std::unary_function <U*, bool> {
private:
typedef R (U::*fn_t)();
fn_t fn;
R val;
public:
explicit mem_fun_eq (fn_t f, R& r) : fn(f), val(r) { }
bool operator() (U * u) const {
return (u->*fn)() == val;
}
};
Thus, if I have:
class Atom {
public:
const Element_t& Element() const { return _element; }
const std::string& Name() const { return _name; }
};
I would like to perform a search on a container of Atoms and check for either the Name or Element equality using my template predicate like so:
typedef std::string (Atom::*fn)() const;
Atom_it it = std::find_if( _atoms.begin(), _atoms.end(), mem_fun_eq <Atom, std::string> ((fn)&Atom::Name, atomname));
but compiling this returns the following error on the std::find_if line:
error: address of overloaded function with no contextual type information
Also, trying to form the same predicate for a check of the Element() as such:
typedef Atom::Element_t& (Atom::*fn)() const;
Atom_it it = std::find_if(_atoms.begin(), _atoms.end(), mem_fun_eq <Atom, Atom::Element_t> ((fn)&Atom::Element, elmt);
creates a different error!
error: no matching function for call to ‘mem_fun_eq<Atom, Atom::Element_t>::mem_fun_eq(Atom::Element_t& (Atom::*)()const, const Atom::Element_t&)’
note: candidates are: mem_fun_eq<U, R>::mem_fun_eq(R (U::*)(), R&) [with U = Atom, R = Atom::Element_t]
note: mem_fun_eq<Atom, Atom::Element_t>::mem_fun_eq(const mem_fun_eq<Atom, Atom::Element_t>&)
Firstly, am I reinventing the wheel with this predicate? Is there something in the STL that I've missed that does the same job in a single class? I can always break the predicate down into several more specific ones, but I'm trying to avoid that.
Secondly, can you help me with the compiler errors?
I don't know of any easy way to do this using the bits provided with the STL. There is probably some clever boost way, using iterator adapters, or boost::lambda, but personally I wouldn't go that way.
Obviously C++0x lambdas will make all this easy.
Your problem is attempting to cast a function like this:
const std::string&(Atom::*)()
into a function like this:
std::string (Atom::*)()
If you replace your typedef R (U::*fn_t)(); with typedef const R& (U::*fn_t)() const; then it should work.
The following avoids this problem and also provides type inference so that you can just write mem_fun_eq(&Atom::Name, atomname). It compiles for me, although I haven't tested it.
template<typename U, typename R, typename S>
class mem_fun_eq_t : public std::unary_function<U const*, bool>
{
private:
R (U::*fn_)() const;
S val_;
public:
mem_fun_eq_t(R (U::*fn )() const, S val) : fn_(fn), val_(val){}
bool operator()(U * u)
{
return (u->*fn_)() == val_;
}
};
template<typename U, typename R, typename S>
mem_fun_eq_t<U, R, S> mem_fun_eq(R (U::*fn)() const, S val)
{
return mem_fun_eq_t<U, R, S>(fn, val);
}
Have you thought of trying to mix in a mem_fun_ref or mem_fun object in place of the member function call?
Basically, you call on mem_fun to create an object that accepts two arguments T* and a template argument to the function A if it has one (or void if it doesn't). Hence you combine it like so:
template<typename MemFunc, typename CompareType, typename T>
struct MyPredicate{
MyPredicate(MemFunc _functionObj, CompareType _value)
: m_Value(_value),
m_Function(_functionObj){}
bool operator()(const T &_input){
return m_Value == m_Function(_input);
}
private:
MemFunc m_Function;
CompareType m_Value;
};
Edit:
Ok, that's not completely working so why not have:
struct NamePred: binary_function<Atom*,string,bool>{
bool operator()(Atom *_obj, string _val){
return _obj->Name() == _val;
};
};
then use bind2nd
find_if( atoms.begin(), atoms.end(), bind2nd( NamePred, "yo" ) );