What's the right way to make a pair with unique_ptr? - c++

I am trying to make_pair with a unique_ptr like in the example below
(The code is a C++ implementation of the Facade Design pattern)
#include <unordered_map>
#include <utility>
#include <functional>
using namespace std;
// Step 1 : Design the Interface
class IAccount {
protected:
int accountNo;
int cash;
public:
virtual void deposit(float amount);
virtual void withdraw(float amount);
virtual void transfer(float amount);
virtual int getAccountNumber() = 0;
};
// Step 2 : Implement the interface with one or more subtypes
class Current : public IAccount{
public:
Current(int amt) { cash = amt; }
int getAccountNumber() {
return accountNo;
}
};
class Savings : public IAccount{
public:
Savings(int amt) { cash = amt; }
int getAccountNumber() {
return accountNo;
}
};
// Step 3: Create the Facade class and wrap the classes that implement the Interface
class BankService {
unordered_map<int, unique_ptr<IAccount>> *bankAccounts;
int index;
public:
BankService(): index(0){
bankAccounts = new unordered_map<int, unique_ptr<IAccount>>();
}
int createNewAccount(string name, int amount, string type, int accountNo) {
unique_ptr<IAccount> newAccount;
if(type.compare("current")) {
newAccount.reset(new Current(amount));
}
// Add to the unordered list --- Error here ---
pair<int, unique_ptr<IAccount>> toBeInserted = make_pair(accountNo, newAccount);
bankAccounts->insert(toBeInserted);
return accountNo;
}
};
The code spits out this error :
/Library/Developer/CommandLineTools/usr/include/c++/v1/vector:266:
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/__bit_reference:15:
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/algorithm:639:
/Library/Developer/CommandLineTools/usr/include/c++/v1/utility:634:12: error: no matching constructor for initialization of 'pair<typename
__make_pair_return<int &>::type, typename __make_pair_return<unique_ptr<IAccount, default_delete<IAccount> > &>::type>' (aka 'pair<int,
std::__1::unique_ptr<IAccount, std::__1::default_delete<IAccount> > >')
return pair<typename __make_pair_return<_T1>::type, typename __make_pair_return<_T2>::type>
^
If I change it to :
// Add to the unordered list (note added const)
pair<const int, unique_ptr<IAccount>> toBeInserted = make_pair(accountNo, newAccount);
bankAccounts->insert(toBeInserted);
I am greeted by :
In file included from ./DesignPatterns/Structural/./../../Include/Common.h:1:
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/vector:266:
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/__bit_reference:15:
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/algorithm:640:
/Library/Developer/CommandLineTools/usr/include/c++/v1/memory:1783:31: error: call to implicitly-deleted copy constructor of 'std::__1::pair<const
int, std::__1::unique_ptr<IAccount, std::__1::default_delete<IAccount> > >'
::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
I tried compiling with with both Clang++ and G++
Clang version: clang-900.0.39.2
G++ version : 4.2.1
Platform: OS x - x86_64-apple-darwin16.6.0
Is this due to the old version of G++ shipped by Apple?

Is this due to the old version of G++ shipped by Apple?
No. It is because you are trying to copy the unique pointer by passing it to make_pair and insert.
std::unique_ptr is not copyable. In fact it is move-only. Change to:
pair<int, unique_ptr<IAccount>> toBeInserted = make_pair(accountNo, std::move(newAccount));
bankAccounts->insert(std::move(toBeInserted));

Related

Returning a map of structs from within a class (where the struct definition is within the class): compile error

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()) {

C++ Template Class with Template Constructor

I tried to implement Properties in c++. I don't no why but if I want to compile my code there are quite a lot of errors. The main Idea was, that a template class and the tamplate constructor will give the requirement Informations.
I would be grateful if somebody could help me!
Compiling Message:
pi#raspberrypi ~/dev/property $ gcc -std=c++0x -o PropertyTest2 PropertyTest2.cpp
PropertyTest2.cpp:22:16: error: expected ‘;’ at end of member declaration
PropertyTest2.cpp:22:19: error: expected unqualified-id before ‘<’ token
PropertyTest2.cpp: In function ‘int main()’:
PropertyTest2.cpp:34:20: error: use of deleted function ‘PropertyTestClass::PropertyTestClass()’
PropertyTest2.cpp:8:7: error: ‘PropertyTestClass::PropertyTestClass()’ is implicitly deleted because the default definition would be ill-formed:
PropertyTest2.cpp:8:7: error: no matching function for call to ‘Property<int>::Property()’
PropertyTest2.cpp:8:7: note: candidates are:
Property4.cpp:21:2: note: template<int (** G)(), void (** S)(int&)> Property::Property()
Property4.cpp:6:7: note: constexpr Property<int>::Property(const Property<int>&)
Property4.cpp:6:7: note: candidate expects 1 argument, 0 provided
Property4.cpp:6:7: note: constexpr Property<int>::Property(Property<int>&&)
Property4.cpp:6:7: note: candidate expects 1 argument, 0 provided
PropertyTest2.cpp:38:20: error: no matching function for call to ‘Property<int>::Set(int)’
PropertyTest2.cpp:38:20: note: candidate is:
Property4.cpp:30:7: note: void Property<T>::Set(T&) [with T = int]
Property4.cpp:30:7: note: no known conversion for argument 1 from ‘int’ to ‘int&’
Property Class (Property.cpp)
#ifndef __PROPERTY_FH__
#define __PROPERTY_FH__
template <class T>
class Property {
private:
typedef T (*TGetter)(void);
typedef void (*TSetter)(T &);
TGetter Getter;
TSetter Setter;
public:
typedef T type;
template<TGetter *G,
TSetter *S
>
Property() {
this->Getter = G;
this->Setter = S;
}
T Get(void) {
return (this->Getter)();
}
void Set(T &value) {
(this->Setter)(value);
}
};
#endif
Testing file (PropertyTest.cpp):
#ifndef __PROPERTY_TEST_FH__
#define __PROPERTY_TEST_FH__
#include <iostream>
#include "Property.cpp"
class PropertyTestClass {
private:
// ReadWrite Property for age
int _age;
int AgeGetter(void) {
return this->_age;
}
void AgeSetter(int &value) {
this->_age = value;
}
public:
// ReadWrite Property for age
Property<int> age<&PropertyTestClass::AgeGetter, &PropertyTestClass::AgeSetter>;
};
#endif
/**
* Program Entry
**/
int main() {
std::cout << "Property Test Programm\n\n";
PropertyTestClass propTest;
std::cout << "ReadWrite Property for age\n";
propTest.age.Set(5);
std::cout << propTest.age.Get() << "\n";
return 0;
}
Ok, this time fixed all the problems in your code.
Property.cpp:
#ifndef __PROPERTY_FH__
#define __PROPERTY_FH__
#include <boost/function.hpp>
template <class T>
class Property {
private:
typedef boost::function <T()> TGetter;
typedef boost::function <void(const T&)> TSetter;
TGetter Getter;
TSetter Setter;
public:
typedef T type;
Property(TGetter G, TSetter S) {
this->Getter = G;
this->Setter = S;
}
T Get(void) {
return (this->Getter)();
}
void Set(const T &value) {
(this->Setter)(value);
}
};
#endif
PropertyTests.cpp:
#ifndef __PROPERTY_TEST_FH__
#define __PROPERTY_TEST_FH__
#include <iostream>
#include <boost/bind.hpp>
#include "Property.cpp"
class PropertyTestClass {
private:
// ReadWrite Property for age
int _age;
int AgeGetter() {
return this->_age;
}
void AgeSetter(const int &value) {
this->_age = value;
}
public:
// ReadWrite Property for age
Property<int> age;
PropertyTestClass() : age(
boost::bind(&PropertyTestClass::AgeGetter, this),
boost::bind(&PropertyTestClass::AgeSetter, this, _1))
{}
};
#endif
/**
* Program Entry
**/
int main() {
std::cout << "Property Test Programm\n\n";
PropertyTestClass propTest;
std::cout << "ReadWrite Property for age\n";
propTest.age.Set(5);
std::cout << propTest.age.Get() << "\n";
return 0;
}
Output:
$ ./a.out
Property Test Programm
ReadWrite Property for age
5

Struct in a list doesn't work

I have this code:
hpp:
#include <list>
using namespace std;
class funcionario
{
public:
struct Dia {
int d;
int h;
int id;
int tipo;
};
funcionario ();
void eliminar(int dia, int hora);
private:
list<Dia> agenda;
};
cpp:
#include "myClass.hpp"
funcionario::funcionario(){
agenda = list<Dia> ();
}
void funcionario::eliminar(int dia, int hora) {
list<funcionario::Dia>::iterator it;
it = agenda.begin();
while(it != agenda.end() && (*it).d <= dia) {
if((*it).d == dia && (*it).h == hora) {
agenda.erase(it);
return;
}
++it;
}
}
I get this compiling error:
Funcionario.cpp: In constructor ‘funcionario::funcionario()’:
Funcionario.cpp:5: error: cannot convert ‘std::list<funcionario::Dia, std::allocator<funcionario::Dia> >’ to ‘int’ in assignment
Funcionario.cpp: In member function ‘void funcionario::eliminar(int, int)’:
Funcionario.cpp:9: error: request for member ‘begin’ in ‘((funcionario*)this)->funcionario::agenda’, which is of non-class type ‘int’
Funcionario.cpp:10: error: request for member ‘begin’ in ‘((funcionario*)this)->funcionario::agenda’, which is of non-class type ‘int’
Funcionario.cpp:11: error: request for member ‘end’ in ‘((funcionario*)this)->funcionario::agenda’, which is of non-class type ‘int’
I don't know what I'm doing wrong.
Not sure what you're trying to achieve, but the code just needs to be fleshed out a bit with complete function definitions. I got this to compile:
#include <list>
class myClass
{
public:
myClass();
struct myStruct {
int myInfo;
};
void something();
void doSomething(myStruct & ms);
private:
std::list<myStruct> myList;
};
myClass::myClass(){
myList = list<myStruct> ();
}
void myClass::something() {
std::list<myStruct>::iterator it;
it = myList.begin();
while(it != myList.end()) {
doSomething(*it);
++it;
}
}
Incidentally (or maybe directly relevant, not sure) - the copy-initialization of myList in myClass() is unnecessary, as others have stated. The list<> default constructor will do the right thing, and more efficiently.
This seems to be working on my computer, so may it be a compiler problem? Try with another compiler and tell us if it worked
The initialization you're looking for is analogous to Initializing map and set class member variables to empty in C++? - but actually you'll get an empty list automatically (i.e. by the std::list default constructor).
--Edited to reflect your posting of the original code--
H is not declared anywhere.
and is not a valid C++ keyword or token. Use &&.
Use the local header include form of : #include "myClass.hpp"

Boost d_ary_heap/priority_queue compile error: deleted function

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.

C++ error: no viable conversion from 'mapped_type' to 'int'

I am trying to implement the a map from the C++ STL as follows:
#include <string>
#include <iostream>
#include <map>
using namespace std;
#include "assembler.h"
// This Class makes use of the Map Template from the Standart Template Library
// All addresses are stored as numerical (Dec) integers
SymbolTable::SymbolTable() { // Constructor
map <string, int> symbolTable;
int address = 0;
}
void SymbolTable::addEntry(string symbol, int address) {
symbolTable[symbol] = address;
address++;
}
// Returns true if symbolTable already contains symbol
bool SymbolTable::contains(string symbol) {
if (symbolTable.find(symbol) == symbolTable.end()) { return true; }
else { return false; }
}
int SymbolTable::getAddress(string symbol) {
return symbolTable[symbol];
}
I try to compile this with
c++ *.cpp -0 assembler.out
and I get the following error message:
symboltable.cpp:57:9: error: no viable conversion from 'mapped_type' (aka 'std::basic_string<char>') to 'int'
return symbolTable[symbol];
^~~~~~~~~~~~~~~~~~~
1 error generated.
I have searched for this error online and all I get is bug reports relating to the STL and I cannot figure out if those reports are the same problem I am having and if so how to get around it. Am I doing something wrong?
I have tried (probably stupidly) to typecast the offending line as
return (int) symbolTable[symbol];
Thank you for any help.
My header file declares the class as:
class SymbolTable {
public:
SymbolTable();
void addEntry(string, int);
bool contains(string);
int getAddress(string);
private:
map <string, string> symbolTable;
int address;
};
This:
SymbolTable::SymbolTable() { // Constructor
map <string, int> symbolTable;
^
^
is a function-local variable, not a member variable. It is not the same as the symbolTable that you're accessing in e.g. getAddress, which presumably is a member variable. You haven't shown the class body, but my guess is that it's defined differently.