I have some pretty simple C++ code that creates points from a struct definition and tries to add those points to a set.
#include <stdio.h> /* printf */
#include <bits/stdc++.h> /* vector of strings */
using namespace std;
struct point
{
int x;
int y;
};
int main(){
for(int i = 0; i <= 6; i++){
set<point> visited_points;
point visited_point{4, 1};
visited_points.insert(visited_point);
}
}
But this code throws a large console error when I run it saying:
In file included from /usr/include/c++/7/string:48:0,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/istream:38,
from /usr/include/c++/7/sstream:38,
from /usr/include/c++/7/complex:45,
from /usr/include/c++/7/ccomplex:39,
from /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h:52,
from ex.cpp:2:
/usr/include/c++/7/bits/stl_function.h: In instantiation of ‘constexpr bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = point]’:
/usr/include/c++/7/bits/stl_tree.h:2038:11: required from ‘std::pair<std::_Rb_tree_node_base*, std::
........
/usr/include/c++/7/bits/stl_function.h:386:20: note: ‘const point’ is not derived from ‘const std::__cxx11::sub_match<_BiIter>’
{ return __x < __y; }
~~~~^~~~~
Is there a part of my code that I did wrong? I just want a way to keep track of multiple points in a list.
Sets are ordered, and so the elements need an ordering function. Your point class doesn't not have this. Add a suitable definition of
bool operator<(const Point& a, const Point& b);
For instance
bool operator<(const Point& a, const Point& b)
{
return a.x < b.x || a.x == b.x && a.y < b.y;
}
But whatever ordering function you choose it must define a strict weak ordering
Related
I want to construct a vector that will hold int M elements of my class Point which represent a single point (x,y) where both x,y are int.
The points that will be stored in this vector are randomly generated. However, I do not want to store the same point more than once.
My implementation is the following:
#include <algorithm>
#include <random>
std::random_device rd;
std::mt19937 mt(rd());
std::vector<Point> InitList(int M)
{
if ( M <=0 )
{
std::cout << "InitList: Length of vector must be greater than zero. Don't play around!"
<< std::endl;
exit(EXIT_FAILURE);
}
Point to_erase(-100,-100); // <----- can I get rid of this?
Point to_add;
int x,y;
std::vector<Point> vec = {};
vec.push_back(to_erase); // <----- and this
while (vec.size() < M+1) // <----- and then M+1 -> M
{
std::uniform_int_distribution<int> RandInt(0,100);
x = RandInt(mt);
y = RandInt(mt);
point.set(x,y);
if ( std::find(vec.begin(), vec.end(),to_add) == vec.end() )
vec.push_back(to_add);
}
vec.erase (vec.begin()); // <----- and finally avoid this?
return vec;
}
How can I avoid the trick of adding the first instance to_erase?
EDIT
So I changed the implementation to use std::unordered_set
and I am getting the following errors:
error: use of deleted function ‘std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set() [with _Value = Site; _Hash = std::hash<Site>; _Pred = std::equal_to<Site>; _Alloc = std::allocator<Site>]’
note: ‘std::hash<Site>::hash()’ is implicitly deleted because the default definition would be ill-formed:
101 | struct hash : __hash_enum<_Tp>
| ^~~~
/usr/include/c++/9/bits/functional_hash.h:101:12: error: no matching function for call to ‘std::__hash_enum<Site, false>::__hash_enum()’
/usr/include/c++/9/bits/functional_hash.h:82:7: note: candidate: ‘std::__hash_enum<_Tp, <anonymous> >::__hash_enum(std::__hash_enum<_Tp, <anonymous> >&&) [with _Tp = Site; bool <anonymous> = false]’
82 | __hash_enum(__hash_enum&&);
| ^~~~~~~~~~~
And the list goes on. I guess there is an implementation missing in my class Point. What should I do?
You can guarantee uniqueness just by using std::set (https://www.cplusplus.com/reference/set/set/) instead of std::vector.
If order doesn't matter, use std::unordered_set.
Regarding the hash issues you're seeing -- you have to define a hash function for a custom type, when using a few C++ types like set, unordered_set, map, etc. This is a function that returns a unique number based on the value of your custom Point instance. I stubbed out this example to give you an idea of how this might work for you, but YMMV:
#include <iostream>
#include <unordered_set>
struct Point
{
int x;
int y;
Point(int x, int y): x(x), y(y) {};
};
bool operator==(const Point& lhs, const Point& rhs)
{
return ((lhs.x == rhs.x) and (lhs.y == rhs.y));
}
namespace std
{
template <>
struct hash<Point>
{
size_t operator()( const Point& p ) const
{
return (p.x << 32 | p.y);
}
};
}
int main() {
Point p1(3,2);
Point p2(3,2);
std::unordered_set<Point> someSet;
someSet.insert(p1);
std::cout << "set size:" << someSet.size() << std::endl;
// set size: 1
someSet.insert(p2);
std::cout << "set size:" << someSet.size() << std::endl;
// set size: 1 (still!)
return 0;
}
If only presence is relevant: std::set.
If you need also occurrence count, you could use std::map<Point, int>, where the int is the count. With some special handling to remove elements when counts gets to zero.
You could replace std::map with std::unordered_map for performance reasons. But ALWAYS test both before deciding.
I have some problem with sorting my vectors.I want to sort my vectors acording to first element wchich is Number.Can someone explain me what I doing wrong and what this 2 errors means?
I try sort this with compare function and without it and nothing works.
struct Point{
int x;
int y;
};
bool compare(int a,int b){
return a < b;
}
int main()
{
int N,Number,x,y;
cin >> N;
vector<pair<int,Point>> p;
for(int i = 0 ; i < N ; i++){
cin >> Number >> x >> y;
pair<int,Point> pom = {Number,{x,y}};
p.push_back(pom);
}
// sort(p.begin(),p.end());
// sort(p.begin().p.end(),compare);
return 0;
}
I've got two errors but I don't know what means:
1.no match for 'operator<' (operand types are 'const Point' and 'const Point')
|| (!(__y.first < __x.first) && __x.second < __y.second); }
2.body of constexpr function 'constexpr bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) [with _T1 = int; _T2 = Point]' not a return-statement
|| (!(__y.first < __x.first) && __x.second < __y.second); }
^
^
Comparator for ints is useless and probably Undefined Behaviour. Compiler knows how to compare two integers, it's part of the language. It also knows how to compare two instances of std::pair. What it doesn't know, is how to compare two instances of Point class, which is defined by you.
Basically, you have two options:
1. Provide operator< for Point
This will let you compare two points easily in any situation later on:
bool operator<(const Point& p1, const Point& p2) {
if (p1.x == p2.x)
{
return p1.y < p2.y;
}
return p1.x < p2.x;
}
2. Provide an in-place comparator for std::sort
This is a quick solution if you only need to compare stuff for sorting purposes.
std::sort(p.begin(), p.end(), [](const auto& p1, const auto& p2) {
//whatever logic it takes to compare two std::pair<int, Point>
});
Note: Generic lambda (with const auto& as arguments) is a C++14 feature. Lambdas themselves are C++11 feature.
Choice between above depends on the usage. If you just need to sort a vector, of if the logic for sorting is unusual, go for std::sort comparator. If you want to always compare two Points in the same way, go for operator overloading.
I basically have an std::deque of objects, and I want to remove some of these objets according a condition on a given member variable of the objects, so that I use a predicate, but I have errors that I don't really understand.
I am using g++ with the -std=c++11 for STL reasons (shared pointers) but I was trying to work this out on windows with MVS with non c++11 code, so that I am looking for a non c++11 solution, without lamdas etc
The code is :
#include <iostream> // for std::cout and std::endl
#include <cstdio> // for getchar()
#include <memory> // for std::shared_ptr
#include <deque> // for std::deque
#include <algorithm> // for std::earse and std::remove_if
class A
{
private:
int _i;
double _d;
public:
A(int i, double d)
{
_i = i;
_d = d;
}
int geti()const
{
return _i;
}
double getValueOnWhichToCheck()const
{
return _d;
}
};
typedef std::shared_ptr<A> A_shared_ptr;
typedef std::deque<A_shared_ptr> list_type;
void PrintDeque(list_type & dq)
{
if (0 == dq.size())
{
std::cout << "Empty deque." << std::endl;
}
else
{
for (int i = 0 ; i < dq.size() ; ++i)
{
std::cout << i+1 << "\t" << dq[i] << std::endl;
}
}
}
class B
{
public:
double getThreshold() // Non constant for a reason as in real code it isn't
{
return 24.987; // comes from a calculation not needed here so I return a constant.
}
bool Predicate(A_shared_ptr & a)
{
return a->getValueOnWhichToCheck() >= getThreshold();
}
void DoStuff()
{
A_shared_ptr pT1 = std::make_shared<A>(A(2, -6.899987));
A_shared_ptr pT2 = std::make_shared<A>(A(876, 889.878762));
A_shared_ptr pT3 = std::make_shared<A>(A(-24, 48.98924));
A_shared_ptr pT4 = std::make_shared<A>(A(78, -6654.98980));
A_shared_ptr pT5 = std::make_shared<A>(A(6752, 3.141594209));
list_type dq = {pT1,pT2,pT3,pT4,pT5};
PrintDeque(dq);
bool (B::*PtrToPredicate)(A_shared_ptr &) = &B::Predicate;
dq.erase(std::remove_if(dq.begin(), dq.end(), PtrToPredicate),dq.end());
PrintDeque(dq);
}
};
int main()
{
B * pB = new B();
pB->DoStuff();
getchar();
}
and the output of g++ -std=c++11 main.cpp -o main is :
In file included from /usr/include/c++/5/bits/stl_algobase.h:71:0,
from /usr/include/c++/5/bits/char_traits.h:39,
from /usr/include/c++/5/ios:40,
from /usr/include/c++/5/ostream:38,
from /usr/include/c++/5/iostream:39,
from main.cpp:1:
/usr/include/c++/5/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Iter_pred<_Predicate>::operator()(_Iterator) [with _Iterator = std::_Deque_iterator<std::shared_ptr<A>, std::shared_ptr<A>&, std::shared_ptr<A>*>; _Predicate = bool (B::*)(std::shared_ptr<A>&)]’:
/usr/include/c++/5/bits/stl_algo.h:866:20: required from ‘_ForwardIterator std::__remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = std::_Deque_iterator<std::shared_ptr<A>, std::shared_ptr<A>&, std::shared_ptr<A>*>; _Predicate = __gnu_cxx::__ops::_Iter_pred<bool (B::*)(std::shared_ptr<A>&)>]’
/usr/include/c++/5/bits/stl_algo.h:936:30: required from ‘_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = std::_Deque_iterator<std::shared_ptr<A>, std::shared_ptr<A>&, std::shared_ptr<A>*>; _Predicate = bool (B::*)(std::shared_ptr<A>&)]’
main.cpp:67:73: required from here
/usr/include/c++/5/bits/predefined_ops.h:234:30: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘((__gnu_cxx::__ops::_Iter_pred<bool (B::*)(std::shared_ptr<A>&)>*)this)->__gnu_cxx::__ops::_Iter_pred<bool (B::*)(std::shared_ptr<A>&)>::_M_pred (...)’, e.g. ‘(... ->* ((__gnu_cxx::__ops::_Iter_pred<bool (B::*)(std::shared_ptr<A>&)>*)this)->__gnu_cxx::__ops::_Iter_pred<bool (B::*)(std::shared_ptr<A>&)>::_M_pred) (...)’
{ return bool(_M_pred(*__it)); }
^
Not a fan of function pointers, but using lambda's this seems to compile... https://ideone.com/0StRcw
dq.erase(std::remove_if(dq.begin(), dq.end(), [this](const std::shared_ptr<A>& a) {
return a->getValueOnWhichToCheck() >= getThreshold();
}),dq.end());
Or without lambdas..
auto predicateToUse = std::bind(&B::Predicate, this, std::placeholders::_1);
dq.erase(std::remove_if(dq.begin(), dq.end(), predicateToUse), dq.end());
Update no auto:
dq.erase(std::remove_if(dq.begin(), dq.end(), std::bind(&B::Predicate, this, std::placeholders::_1)), dq.end());
You are not going to be able to use a non static member function pointer with remove_if. remove_if requires a normal function pointer, static member function pointer or a function object. The reason it cannot use a member function pointer is because it needs an instance of the class in order to be able to call the function and you cannot wrap that into the call
You are either need to make Predicate static, create a function object and pass an instance of that, or use a lambda in the call site.
So thanks to C++11, it's now possible to combine macros, user-defined literals, lambdas, etc. to create the closest I can get to 'syntactic sugar'. An example would be
if (A contains B)
Of course this is easy.
cout <<("hello"_s contains "ello"_s)<<endl;
The expression converts to a bool, where contains is a custom struct that takes the left-hand side and right-hand side as arguments. The struct of course overloads operator+ to take the custom string literal first, returning itself, then the operator+ for the struct itself.
struct contains_struct {
string lhs;
string rhs;
void set_lhs(string lhs) { this->lhs = lhs; }
void set_rhs(string rhs) { this->rhs = rhs; }
operator bool() const {
return string::npos != lhs.find(rhs);
}
} contains_obj;
contains_struct& operator+(const string& lhs, const contains_struct& rhs) {
contains_obj.set_lhs(lhs);
return contains_obj;
}
contains_struct& operator+(const contains_struct& lhs, const string& rhs) {
contains_obj.set_rhs(rhs);
return contains_obj;
}
#define contains +contains_obj+
Now I decided I want to go further. What about
(x in a) perform cube
It's no list comprehension, but it's a pretty good example right? At first I said, well I'd have to go to stackoverflow to ask about custom operator precedence, but it's straight forward to put it in parentheses since no one in their right mind would use my code. Instead, I expanded upon my other example and have 'in' and 'perform' as custom structs, just like 'contains'.
You can go further and template it so that x can be any numerical index, and a as any container, but for simplicity, I left x as an integer and a as a vector of ints. Now so far it doesn't actually take the local variable x as an argument, it uses it locally in the operator string() function.
To simplify things, I store the results of the expression in a string, like so
operator string() const {
string s = "";
for (int x : lhs.rhs)
s += to_string(rhs(x)) + string("\n");
return s;
}
Thanks to another question: Overloading assignment operator for type deduction
I realized one practical use for returning it as an assignment is the following:
struct result_struct {
vector<int> results;
result_struct(vector<int> results) { this->results = results; }
};
...
operator result_struct() const {
vector<int> tmp;
for (int x : lhs.rhs)
tmp.push_back(rhs(x));
return result_struct(tmp);
}
...
result_struct result_2 = (x in a) perform cube;
for (int x : result_2.results)
cout <<x<<endl;
Thanks to milleniumbug's answer, I can do:
struct for_obj
{
int _lhs;
std::vector<int> _rhs;
for_obj(int lhs, std::vector<int> rhs)
: _lhs(lhs), _rhs(rhs) { }
};
INFIX_OPERATOR(for_obj, in_op, int, std::vector<int>)
{
return for_obj(lhs(), rhs());
}
#define in + in_op() +
INFIX_OPERATOR(int, perform_op, for_obj, std::function<int(int)>)
{
for (int i = 0; i < lhs()._rhs.size(); i++)
rhs()(lhs()._rhs[i]);
return 0;
}
#define perform + perform_op() +
There are two caveats. First, I return an int so that I can assign it to a dummy variable to get it to execute. I could always do the result_struct thing I did before, or return a std::function object to call it by itself, but I'd be repeating myself. The other caveat is that because there are so many consts in the macro, you cannot modify the lhs (which doesn't allow you to specifiy an iterator).
All things considered, the following works as expected.
int x = 0;
std::vector<int> nums = { 1, 2, 3 };
auto cube = [] (int x)
{
std::cout << x * x * x << std::endl;
return x * x * x;
};
int i = (x in nums) perform cube;
New version
class PerformObj {
int counter;
public:
PerformObj() : counter(0) { }
~PerformObj() { }
InObj lhs;
std::function<int(int)> rhs;
operator int() const {
return rhs(lhs.rhs[counter]);
}
} performobj;
#define perform + performobj +
PerformObj& operator+(const InObj& lhs, PerformObj& rhs) {
rhs.lhs = lhs;
return rhs;
}
PerformObj& operator+(PerformObj& lhs, const std::function<int(int)>& rhs) {
lhs.rhs = rhs;
return lhs;
}
int main()
{
std::vector<int> nums = {1,2,3};
int x = 0;
auto cube = [] (int n) {
return n * n * n;
};
std::cout << x in nums perform cube << std::endl;
}
explicit operator std::vector<int>() const {
std::vector<int> temp;
for (int i = 0; i < lhs.rhs.size(); i++) {
temp.push_back(rhs(lhs.rhs[i]));
}
return temp;
}
int y = 0;
std::cout << y in static_cast<std::vector<int>>(x in nums perform cube) perform std::function<int(int)>([] (int i) -> int {
return i;
}) << std::endl;
Should I make it so that instead of infix operators, there are postfix operators, like "String literal"s.contains "Other string literal"s, or do it function style, "String literal"s.contains("Other string literal"s)?
How would I improve my code to make it more extensible? As it is right now, it's very polluted. Is there a better/more generalized/less clunky way to do this? For example, to generalize the expressions so that I don't need define statements or to reuse code.
It is hard to see what is the question asked here, assuming the latest edit has all the questions.
Should I make it so that instead of infix operators, there are postfix
operators, like "String literal"s.contains "Other string literal"s, or
do it function style, "String literal"s.contains("Other string
literal"s)?
Yes. "String literal"s.contains("Other string literal"s) is the best way - concise, clear to C++ programmers, clear to programmers of other languages (Java and Python strings have methods) and no template magic nor macro magic is used.
How would I improve my code to make it more extensible? As it is right
now, it's very polluted. Is there a better/more generalized/less
clunky way to do this? For example, to generalize the expressions so
that I don't need define statements or to reuse code.
Yep! But only to certain degree (removed the unnecessary consts over there and here):
#define INFIX_OPERATOR(rettype, name, LT, RT) \
struct name\
{\
private:\
LT* left;\
RT* right;\
\
protected:\
LT& lhs() const { return *left; }\
RT& rhs() const { return *right; }\
\
public: \
friend name operator+(LT& lhs, name && op)\
{\
op.left = &lhs;\
return op;\
}\
\
friend name operator+(name && op, RT& rhs)\
{\
op.right = &rhs;\
return op;\
}\
\
name () : left(nullptr), right(nullptr) {}\
\
operator rettype() const;\
};\
\
inline name :: operator rettype() const
And then you can create your infix operator like this:
#include <iostream>
#include <string>
INFIX_OPERATOR(bool, contains_op, const std::string, const std::string)
{
return std::string::npos != lhs().find(rhs());
}
#define contains + contains_op() +
int main()
{
std::string a = "hello";
std::string b = "hell";
if(a contains b)
std::cout << "YES";
}
Note that there is no way to avoid #define contains directive, as there is no way to create macro directive with another macro directive.
What are the practical benefits of this if there are any (ignoring all
rationality of using this as real world code. I mean what can you get
out of it for what I'm using it for, barring recreational purposes?)
Say that my friend, instead of learning C++, wants an easy abstracted
interface for his Bash or Perl experience but would like to
collaborate without resorting to compiling/linking outside gcc. That
way, he can write 'scripts' or 'code' that is C++, and compile and
link it with my programs/libraries/interface, whatever.
It seems that you are trying to create a language on top of another language. Prepare for
Hours and hours trying to test your language.
Embarrassingly bad diagnostics messages. Try to compile this: std::vector<void> myarr;1 Then wrap it with macros. And then wrap it in another template. And then in another macros... You get the idea.
Debugging tools showing processed code.
Even if your language perfectly integrates with itself, you still have C++ to take care of, with tons of rules and complicated type system. After all, all abstractions are leaky.
If your friend want to program in Perl, just let him do it. These languages are easy to interface with C.
If you're trying to create a language, because the other languages can't cleanly express what you're trying to do, parser generators (Flex/Bison, ANTLR) and LLVM make it easy.
If creating a parser is overkill, take a look at D language mixins. They accept a string created at compile time, and then compile it as if it was inserted directly.
Here...
import std.stdio;
int main()
{
mixin(`write("Hello world");`); //`contents` is a raw string literal
return 0; //so is r"contents"
}
is equivalent to:
import std.stdio;
int main()
{
write("Hello world");
return 0;
}
This is just a simple example. You could have your function that parses a string:
mixin(user1508519s_language(r"(x in a) perform cube"));
1 - Here is how it looks (gcc 4.7.2):
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/bits/stl_construct.h:63:0,
from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:63,
from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ext/alloc_traits.h
: In instantiation of 'struct __gnu_cxx::__alloc_traits<std::allocator<void> >':
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
76:28: required from 'struct std::_Vector_base<void, std::allocator<void> >'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
208:11: required from 'class std::vector<void>'
#templateerrors2.cpp:5:19: required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ext/alloc_traits.h
:189:53: error: no type named 'reference' in 'class std::allocator<void>'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ext/alloc_traits.h
:190:53: error: no type named 'const_reference' in 'class std::allocator<void>'
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:65:0,
from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
In instantiation of 'class std::vector<void>':
#templateerrors2.cpp:5:19: required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
292:7: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
467:7: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
684:7: error: invalid parameter type 'std::vector<void>::value_type {aka void}'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
684:7: error: in declaration 'void std::vector<_Tp, _Alloc>::resize(std::vector<
_Tp, _Alloc>::size_type, std::vector<_Tp, _Alloc>::value_type)'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
881:7: error: forming reference to void
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:70:0,
from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/vector.tcc:10
8:5: error: forming reference to void
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:65:0,
from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
1003:7: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
1179:7: error: forming reference to void
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:70:0,
from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/vector.tcc:21
6:5: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/vector.tcc:43
9:5: error: forming reference to void
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/vector.tcc:31
6:5: error: forming reference to void
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:65:0,
from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
In instantiation of 'std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp
= void; _Alloc = std::allocator<void>]':
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
247:15: required from 'std::vector<_Tp, _Alloc>::vector() [with _Tp = void; _A
lloc = std::allocator<void>]'
#templateerrors2.cpp:5:19: required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
161:9: error: invalid use of 'void'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
In instantiation of 'void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(std::_V
ector_base<_Tp, _Alloc>::pointer, std::size_t) [with _Tp = void; _Alloc = std::a
llocator<void>; std::_Vector_base<_Tp, _Alloc>::pointer = void*; std::size_t = u
nsigned int]':
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
161:9: required from 'std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _T
p = void; _Alloc = std::allocator<void>]'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
247:15: required from 'std::vector<_Tp, _Alloc>::vector() [with _Tp = void; _A
lloc = std::allocator<void>]'
#templateerrors2.cpp:5:19: required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
175:4: error: 'struct std::_Vector_base<void, std::allocator<void> >::_Vector_im
pl' has no member named 'deallocate'
In file included from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/bits/stl_algobase.h:66:0,
from c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/
c++/vector:61,
from #templateerrors2.cpp:1:
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_iterator_
base_types.h: In instantiation of 'struct std::iterator_traits<void*>':
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_construct
.h:127:24: required from 'void std::_Destroy(_ForwardIterator, _ForwardIterato
r) [with _ForwardIterator = void*]'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_construct
.h:155:7: required from 'void std::_Destroy(_ForwardIterator, _ForwardIterator
, std::allocator<_T2>&) [with _ForwardIterator = void*; _Tp = void]'
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_vector.h:
403:9: required from 'std::vector<_Tp, _Alloc>::~vector() [with _Tp = void; _A
lloc = std::allocator<void>]'
#templateerrors2.cpp:5:19: required from here
c:\__moje\prog\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/bits/stl_iterator_
base_types.h:182:43: error: forming reference to void
I'm writing a program to get a convex hull. I need to sort the points by polar angle, and I chose a base point before, so I write a member compare function ( notice that, for each object the base point is different ). But when I'm applying it to the std::sort, the program can't compile.
Here is my program:
class ConvexHull
{
Point p[MAXN], base;
public:
int size;
void Create(Point (&)[MAXN], const int);
bool cmp(const Point& a, const Point& b) const
{
static int tmp;
return (tmp = CrossProduct(base, a, base, b)) < 0 || (tmp == 0 && Dist(base, a) < Dist(base, b));
}
};
void ConvexHull::Create(Point (&a)[MAXN], const int n)
{
base = a[0];
for (int i = 1; i < n; ++i)
if (a[i].x < base.x || (a[i].x == base.x && a[i].y < base.y))
base = a[i];
std::sort(a, a+n, cmp);
p[0] = a[0], p[1] = a[1];
size = 2;
for (int i = 2; i < n; ++i)
{
while (size >= 2 && CrossProduct(a[i], p[size-1], a[i], p[size-2]) <= 0) --size;
p[size++] = a[i];
}
p[size++] = p[0];
}
and here is the error:
poj1113.cc: In member function 'void ConvexHull::Create(Point (&)[1000], int)':
poj1113.cc:41:24: error: no matching function for call to 'sort(Point [1000], Point*, <unresolved overloaded function type>)'
poj1113.cc:41:24: note: candidates are:
In file included from /usr/include/c++/4.7/algorithm:63:0,
from poj1113.cc:3:
/usr/include/c++/4.7/bits/stl_algo.h:5463:5: note: template<class _RAIter> void std::sort(_RAIter, _RAIter)
/usr/include/c++/4.7/bits/stl_algo.h:5463:5: note: template argument deduction/substitution failed:
poj1113.cc:41:24: note: candidate expects 2 arguments, 3 provided
In file included from /usr/include/c++/4.7/algorithm:63:0,
from poj1113.cc:3:
/usr/include/c++/4.7/bits/stl_algo.h:5499:5: note: void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = Point*; _Compare = bool (ConvexHull::*)(const Point&, const Point&)const]
/usr/include/c++/4.7/bits/stl_algo.h:5499:5: note: no known conversion for argument 3 from '<unresolved overloaded function type>' to 'bool (ConvexHull::*)(const Point&, const Point&)const'
How to fix it? And is this ( I mean make the base member ) a bad deisgn?
The problem is that your cmp method needs to be static. The reason is that non-static methods expect an invisible first argument, the this pointer. The std::sort function do not pass this extra argument.
Since you reference member variables you can't make the function static, but there are other ways to solve this. I recommend using a new C++11 standard functionality, std::bind:
std::sort(a, a+n, std::bind(&ConvexHull::cmp, this));
The std::bind call creates a callable object, setting the first parameter to this so it will be correct when being called.