I am using a Dijkstra for finding a shortest path in graph. I used to use std::set but I think a heap could perform better. But I am having troubles using the d_ary_heap or the priority_queue.
This is a simplified version:
#include <string>
#include <inttypes.h> // for uint32_t
#include <boost/heap/fibonacci_heap.hpp>
#include <boost/heap/binomial_heap.hpp>
#include <boost/heap/d_ary_heap.hpp>
#include <boost/heap/priority_queue.hpp>
using namespace std;
struct __attribute__ ((__packed__)) __attribute__((aligned(8)) Cmp {
// Do *not* reorder the following two fields or comparison will break.
const int32_t _id;
const float _cost;
Cmp(int32_t id, float cost) : _id(id), _cost(cost) {
}
};
struct Entry {
Cmp _cmp;
string str = "some variable";
Entry(int32_t id, float cost) : _cmp(id, cost) {}
Entry(Entry &&e) : _cmp(e._cmp._id, e._cmp._cost) {}
Entry(const Entry &e) : _cmp(e._cmp._id, e._cmp._cost) {}
};
template<class T>
struct gt_entry: public binary_function <T, T, bool>
{
bool operator()(const T &l, const T &r) const
{
return *(int64_t const *)&l > *(int64_t const *)&r;
}
};
typedef boost::heap::d_ary_heap<
Entry,
boost::heap::arity<2>,
boost::heap::compare<gt_entry<Entry> > > DHeap;
typedef boost::heap::binomial_heap<
Entry,
boost::heap::compare<gt_entry<Entry> > > BHeap;
typedef boost::heap::fibonacci_heap<
Entry,
boost::heap::compare<gt_entry<Entry> > > FHeap;
typedef boost::heap::priority_queue<
Entry,
boost::heap::compare<gt_entry<Entry> > > PQueue;
int main() {
//DHeap h; // Doesn't compile
//PQueue h; // Doesn't compile
//BHeap h; // Works but slower than FHeap
FHeap h; // Works but only 3% performance increase vs std::set
h.push(Entry(1, 500.1));
h.top();
h.pop();
return 0;
}
(I am using the packaging of the _cost and _id to speed up comparison, see C++ Optimize if/else condition if you are interested.)
This seems to be the relevant error line, I guess it has something to do with the move or copy constructor.
.../move.h:177:7: error: use of deleted function ‘Entry& Entry::operator=(const Entry&)’
heaps.cpp:19:8: note: ‘Entry& Entry::operator=(const Entry&)’ is implicitly declared as deleted because ‘Entry’ declares a move constructor or move assignment operator
I am using gcc 4.6 (-std=c++0x) and boost 1.50.
Your gcc version does not implement the rules for implicitly deleted functions correctly. The code works at least with gcc 4.7.
A quick workaround is to declare the move assignment operator Entry& operator=(Entry&&) as well.
In general I wouldn't recommend using C++11 with a compiler that is not completely up-to-date.
Also: You move constructor and copy constructor behave odd. They don't copy/move the string. You might want to change that. If you really only need one string across, make it a static member.
Related
I have a container class like this
class Container {
public:
Container(const std::string name, const double value)
: name(name), value(value),{};
const std::string name;
const double value;
};
and I like to initialise a const std::vector<Container>.
This
const std::vector<Container> sets{{"foo", 0}, {"bar", 1}};
works fine using the intel compiler (version 15.0.3 (gcc version 4.8.2 compatibility)) and c++11 enable (-std=c++11)this works with RedHat6, but it fails under Windows7. The compiler is the very same, but the front end is visual studio 2013.
I get the error message:
no operator "=" matches these operands
operand types are: Container = Container
_Right = _Move(_Tmp);
Do I need to write my own copy constructor?
The full example is
#include <vector>
#include <string>
class Container {
public:
Container(const std::string name, const double value) : name(name), value(value){};
const std::string name;
const double value;
};
int main() {
const std::vector<Container> sets{{"foo", 0.0},{"bar", 1.0}};
}
I tried compiling your code with VS2015, and it compiles fine.
I think you simply hit a compiler bug. I would suggest upgrading your C++ compiler to a newer version with better modern C++ support.
P.S. Note that VS2015 supports Windows 7 as well.
I have a map like so map<string, unique_ptr<Base>> variables and I am trying to insert data into the map variables.insert(make_pair("foo", new Int(10))) but I am getting to following errors:
error: no matching function for call to ‘std::map<std::__cxx11::basic_string<char>, std::unique_ptr<Base>>::insert(std::pair<const char*, Int*>)’
variables.insert(make_pair("test", new Int(10)));
error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
template<typename _Pair, typename = typename
This is my code:
class Base {
public:
Base() {};
virtual ~Base() {};
};
class Int : public Base {
public:
Int(int i) {
this->i = i;
}
Int operator=(int i) {
this->i = i;
}
int i;
};
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", new Int(10)));
}
I think I need a fresh pair of eyes to look at this I'm not sure what this issue is, thanks!
Edit
I'm trying to make a heterogeneous map and there's a class for each data type. But I still get the same error no matter how many there are.
Note: This answer only applies to older versions of the main three compilers:
GCC: Applies to 5.3.1 or earlier. May apply to any version earlier than 6.1.0, but I haven't tested this.
Clang: Applies to 3.7.1 or earlier. May apply to any version earlier than 3.8.0, but I haven't tested this.
Visual Studio: Applies to 19.00.23506.0 or earlier. May apply to any version earlier than 19.00.23720.0, but I haven't tested this.
Conversely, if you have GCC 6.1.0 or later, Clang 3.8.0 or later, or Visual Studio 19.00.23720.0 or later, the original code should compile as is, without either of the modifications suggested in this answer.
[Thanks goes to AndyG for pointing out that it works with later versions of GCC & Clang.]
The problem appears to be that it isn't creating your unique_ptr from your raw pointer.
If you can use C++14, try std::make_unique().
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", make_unique<Int>(10)));
}
If you can't, then try something like this:
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", unique_ptr<Int>(new Int(10))));
}
Interestingly, I noticed a slight difference in how different compilers handle this. Using the following slightly modified version of your code as a test program:
#include <map>
#include <memory>
#include <iostream>
class Base {
public:
Base() {};
virtual ~Base() {};
};
class Int : public Base {
public:
Int(int i) {
this->i = i;
}
Int& operator=(int i) {
this->i = i;
// You forgot to return something.
return *this;
}
int i;
};
void set() {
using namespace std;
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", new Int(10)));
// C++14:
// variables.insert(make_pair("test", make_unique<Int>(10)));
// C++11:
// variables.insert(make_pair("test", unique_ptr<Int>(new Int(10))));
// Cheap hack for testing.
cout << static_cast<Int*>(variables["test"].get())->i << endl;
}
int main() {
set();
}
Most compilers* will fail to compile this, unless the initial line is commented out and either of the fixes is uncommented. However, the online MSVC compiler seemed to be able to compile it fine, without needing to uncomment either of the lines. Curiously, the version of MSVC available on Rextester failed to compile it without uncommenting one of the two lines.
* Tested online, with TutorialsPoint GCC, MSVC 2015 online, and Rextester Clang, GCC, and MSVC.
I have a class, and within that class I define a struct. The struct has overloaded comparison operators so that it can be used with a map (with an int as the key).
Prior to messing with classes, I had the struct defined in a .cc file, and that file also contained a function which returned a map of this struct. It worked.
Now I want to have the struct defined in the class header, and the class should have a function which returns a map of structs.
Here is a simplified version of my code, which compiles with the same error as the full version. I don't understand the error, and would appreciate any help!
Cheers.
myclass.h:
#include <map>
class myclass {
public:
struct mystruct {
int i;
mystruct();
mystruct(int j);
bool operator==(const mystruct& rhs);
bool operator>(const mystruct& rhs);
bool operator<(const mystruct& rhs);
};
::std::map<int,mystruct> getStructMap();
};
myclass.cc:
#include <map>
#include "myclass.h"
myclass::mystruct::mystruct(int j) : i(j) {};
myclass::mystruct::mystruct() : i(-1) {};
bool ::myclass::mystruct::operator==(const ::myclass::mystruct& rhs) {return i==rhs.i; }
bool ::myclass::mystruct::operator>(const ::myclass::mystruct& rhs) {return i>rhs.i; }
bool ::myclass::mystruct::operator<(const ::myclass::mystruct& rhs) {return i<rhs.i; }
::std::map<int,::myclass::mystruct> ::myclass::getStructMap() {
::std::map<int,::myclass::mystruct> structMap;
for (int i=0;i<5;i++) structMap[i]=::myclass::mystruct(i);
return structMap;
}
myprogram.cc:
#include <iostream>
#include <map>
#include "myclass.h"
int main() {
myclass myobj;
::std::map<int,::myclass::mystruct> mymap;
mymap=myobj.getStructMap();
}
compile error:
> g++ -o myprogram myprogram.cc myclass.cc
myclass.cc:12: error: ‘class std::map<int, myclass::mystruct, std::less<int>,std::allocator<std::pair<const int, myclass::mystruct> > >::myclass’ has not been declared
myclass.cc:12: error: ISO C++ forbids declaration of ‘getStructMap’ with no type
myclass.cc: In function ‘int getStructMap()’:
myclass.cc:15: error: cannot convert ‘std::map<int, myclass::mystruct, std::less<int>, std::allocator<std::pair<const int, myclass::mystruct> > >’ to ‘int’ in return
Currently your code in parsed as
/*missing type*/ ::std::map<int,::myclass::mystruct>::myclass::getStructMap()
Thus, first error, map doesn't have myclass member (or subclasses, method, typedef, ...)
then the second error : no return type (so assuming int and thus the conversion error).
So to solve that, in myclass.cc, you may remove extra :: as follow:
::std::map<int,::myclass::mystruct> myclass::getStructMap() {
or add extra parenthesis:
::std::map<int,::myclass::mystruct> (::myclass::getStructMap()) {
I want to sort a std::map based on the data (second field). However the second field itself is a structure and I want to sort based on one of its elements. Based on what is suggested here and its reference, decided to copy the map to a vector and then use std::sort. Here is the class implementtion
#include <iostream>
#include <vector>
#include <map>
#include <utility>
class foo() {
foo() {}
void bar()
{
aDeltaMap theDeltaMap;
// insert some elements to theDeltaMap
aDeltaVector theDeltaVec( theDeltaMap.begin(), theDeltaMap.end() );
std::sort(theDeltaVec.begin(), theDeltaVec.end(), descend_rep<deltaPair>() ); //ERROR
}
private:
typedef struct entry {
entry( int r, int mc ) : rep(r), missCounter(mc) {}
int rep;
int missCounter;
} aDeltaEntry;
typedef std::map< int, aDeltaEntry > aDeltaMap;
typedef std::pair< int, aDeltaEntry > deltaPair;
typedef std::vector< deltaPair > aDeltaVector;
struct descend_rep
: std::binary_function<deltaPair,deltaPair,bool>
{
inline bool operator()(const deltaPair& lhs, const deltaPair& rhs) { return lhs.second.rep > rhs.second.rep; };
};
};
At the line of sort function, I get this error
error C2275: illegal use of this type as an expression
error C2059: syntax error : ')'
What did I missed?
One error is that descent_rep is not a class template, so you need to replace
descend_rep<deltaPair>()
by
descend_rep()
You should make descend_rep's bool operator() const too, since comparing its operands does not change its state.
I asked this question already on http://www.cplusplus.com/forum/general/96128/ but to no avail.
does anybody experienced the same bug with g++ 4.2: internal compiler error: in make_thunk, at cp/method.c:129
I think it is not neccessary to include sample code. The respective code compiles without warnings and errors on several other newer g++ versions, as well as on clang++. It is simply correct and the bug was mentioned in the GCC's bugzilla (even several times, because it seems to recurr often), but no workaround was provided.
Please don't tell also to use a newer g++. I MUST compile it on the g++ shipped with Ubuntu Hardy, so I cannot change the compiler. Main development is done on Ubuntu Precise, but I need to keep it compatible to Hardy.
I have no idea what a thunk should be, I only suspect it has to do with covariants and/or multiple inheritance. Also I have several more similar structured header files, which all compile well, despite the only change is the name is the name of the class and I have no aim, to change that because of a compiler bug on Hardy.
Another fact is, it happens at include time.
In file included from /home/heiko/hgl/src/compiler/compilerprojectfactory.cpp:18:
/home/heiko/hgl/src/compiler/compilertype.h: In instantiation of 'HGL::Compiler::CompilerType<HGL::Vector2D, HGL::Compiler::CompilerBase>':
/home/heiko/hgl/src/compiler/compilervector2d.h:23: instantiated from here
/home/heiko/hgl/src/compiler/compilertype.h:22: internal compiler error: in make_thunk, at cp/method.c:129
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
For Debian GNU/Linux specific bug reporting instructions,
see <URL:file:///usr/share/doc/gcc-4.2/README.Bug
EDIT: Here the header which causes the bug:
#include "compilertype.h"
#include "vector2d.h"
namespace HGL {
class Vector2D;
namespace Compiler {
/**
#author Heiko Schäfer <heiko#rangun.de>
*/
class _LOCAL Vector2D : public Compiler::CompilerType<HGL::Vector2D> {
DISALLOW_COPY_AND_ASSIGN(Vector2D)
public:
Vector2D(float x, float y, int line);
using IType::operator=;
virtual operator HGL::Vector2D &() const throw(InvalidExpressionException);
protected:
virtual ~Vector2D();
void append(ISerializeable::BUFFER *dest, const HGL::IType *type) const;
};
}
}
Here the template:
#include "compilerbase.h"
#include "iproject.h"
#include "util.h"
namespace HGL {
namespace Compiler {
const IProject::VSTRUCT minReq = { HGL_MINREQ_MAJOR, HGL_MINREQ_MAJOR, HGL_MINREQ_MAJOR };
template<class Type, class Base = CompilerBase>
class _LOCAL CompilerType : public Type, public Base {
DISALLOW_COPY_AND_ASSIGN(CompilerType)
public:
using IType::operator=;
template<class Param>
inline CompilerType(const Param &p, bool b, int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) :
Type(p), Base(line, b) {
init(vs);
}
template<class Param>
inline CompilerType(const Param &p, int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) : Type(p), Base(line) {
init(vs);
}
inline CompilerType(bool b, int line, const IProject::VSTRUCT &vs = IProject::VSTRUCT())
: Type(), Base(line, b) {
init(vs);
}
template<class Param1, class Param2>
inline CompilerType(const Param1 &p1, const Param2 &p2, int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) :
Type(p1, p2), Base(line) {
init(vs);
}
template<class Param1, class Param2>
inline CompilerType(const Param1 &p1, const Param2 &p2, bool b, int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) : Type(p1, p2),
Base(line, b) {
init(vs);
}
inline CompilerType(int line,
const IProject::VSTRUCT &vs = IProject::VSTRUCT()) : Type(), Base(line) {
init(vs);
}
inline virtual void append(ISerializeable::BUFFER *dest, const IType *type) const {
Base::append(dest, type);
}
protected:
inline virtual ~CompilerType() {}
inline virtual void init(const IProject::VSTRUCT &vs) {
const_cast<IProject::VSTRUCT &>(vs) = std::max(vs, minReq);
CompilerBase::setMinRequiredVersion(vs, Type::getSerialID());
}
};
}
}
RESOLVED!
After digging in g++ 4.2's source code I found out that it needs to now about all types in the complete tree. g++ > 4.2 apparently doesn't need this.
So, the error was in a related class which had a template member with a forwarded specialization. I just included the header instead of forwarding and g++ 4.2 was happy.
Otherwise it is really a non-nice bug not to give an error, but this useless message.
A thunk or trampoline is a piece of code that is added in some implementations of dynamic dispatch to adapt the interface of the base virtual function with respect to the final overrider being used. As you mentioned it is commonly needed to adapt the this pointer in multiple/virtual inheritance (for bases listed after the first non-empty one) and to adapt the resulting pointer/reference with covariant return types.
The error indicates that it is a compiler bug. If you have to use that particular compiler you will need to work around the issue, and that will involve changing your design. You can try to limit the use of multiple/virtual inheritance, reorder the bases in the list or try to play around until you manage to get the compiler to digest that code somehow. If it is a problem when generating the adapter for a covariant return type, consider removing the covariant return and provide an overload (with a different name) that will return the covariant type (i.e. replace covariant return with a non-virtual function returning the most derived type and a virtual function that calls the previous and returns a reference to the base).
Other than those generic hints, without seeing the code you have and the implementation of the compiler there is little else to say.