Visual Studio 2010 list copy construct throwing C2664 error - c++

SOLVED: Restarted Visual Studio
I'm working on a project for school involving the STL list. and getting this error with xmemory. I'm just trying to build the solution at this point, butxmemory is killing me
Error 1 error C2664: 'GroceryStoreItem::GroceryStoreItem(GroceryStoreItem &)' : cannot convert parameter 1 from 'std::string' to 'GroceryStoreItem &' d:\microsoft visual studio 10.0\vc\include\xmemory 208
Here's my header
#include <string>
#include <sstream>
#include<iostream>
#include <iterator>
#include <list>
using namespace std;
//
//*****************************************************************
// USER DEFINED DATA TYPES
//
class GroceryStoreItem
{
friend ostream & operator<< (ostream &out, const GroceryStoreItem &RHS);
public:
GroceryStoreItem();
GroceryStoreItem(string Name, double cost, string location);
GroceryStoreItem(GroceryStoreItem & GroceryStoreItemCCIn);
GroceryStoreItem & operator= (const GroceryStoreItem &RHS);
string ReturnItemName();
string ReturnLocation();
double ReturnCost();
private:
string ItemName;
string Location;
double Cost;
};
and the implementation
#include "Grocery_Item.h"
using namespace std;
//*****************************************************************
// Grocery Item Constructors
//*****************************************************************
GroceryStoreItem::GroceryStoreItem()
{
ItemName = "default";
Location = "aisle 1";
Cost = 0.0;
}
GroceryStoreItem::GroceryStoreItem(string InName, double InCost, string InLocation)
{
ItemName = InName;
Location = InLocation;
if(InCost >= 0.0f)
{
Cost = InCost;
}
else
{
Cost = 0.0f;
}
}
GroceryStoreItem::GroceryStoreItem(GroceryStoreItem & GroceryStoreItemCCIn) //Copy Constructor
{
ItemName=GroceryStoreItemCCIn.ItemName;
Location=GroceryStoreItemCCIn.Location;
Cost=GroceryStoreItemCCIn.Cost;
}
edit
xmemory error in the last line of
template<class _Other>
void construct(pointer _Ptr, _Other&& _Val)
{ // construct object at _Ptr with value _Val
::new ((void _FARQ *)_Ptr) _Ty(_STD forward<_Other>(_Val));

You need to make your copy constructor argument const
GroceryStoreItem::GroceryStoreItem(const GroceryStoreItem& GroceryStoreItemCCIn)
Also it's generally better to use initialisation not assignment in your copy constructor
GroceryStoreItem::GroceryStoreItem(const GroceryStoreItem& rhs) :
ItemName(rhs.ItemName),
Location(rhs.Location),
Cost(rhs.Cost)
{
}
Finally (and this is the most important lesson of all) because you have done the right thing and used std::string internally in your class you don't actually need a copy constructor at all. The compiler generated default will do the right thing anyway. So I would actually delete your copy constructor, this will also fix the error.
Same argument for your assignment operator, delete that too.

I closed Visual Studio, started a new project and pasted my CPPs and Headers into the new project, and it compiled and worked. Not the ideal answer, but it worked.

Related

Visual Studio 2017: How to make intellisense accept friend conversion constructor from other class?

I am following a book with chapter about conversions from 2008. Compiling on visual studio 2017 C++ project.
In the book there was an example on the use of conversion constructor where classes "complex" and "number" exist and "number" can be converted into "complex" through the use of constructor where class "number" befriends the constructor of class "complex" to let it use "number" private properties (as much as I understand).
And the code sample from the book (copied word to word) makes intellisense not happy as it doesn't see friend "complex(number)" constructor and I do not know why.
Code is as below:
#include <string>
class number;
class complex;
int main()
{
return 0;
}
class complex
{
private:
double real;
double imaginary;
public:
complex(double r = 0, double i = 0) : real(r), imaginary(i) {}
complex(number);
};
class number
{
double n;
std::string description;
//friend complex::complex(number); // finds no instance of overload of function complex::complex
public:
number(int k, std::string t = "no description") : n(k), description(t) {}
};
complex::complex(number ob)
{
//real = ob.n; //no friend, no access to private property
imaginary = 0;
}
My question is, why is "friend complex::complex(number);" not visible by intellisense ?
Image of error from the IDE
You can think of this as a bug in intellisense itself. But you can work around it by hiding the code in question. For example,
#ifdef __INTELLISENSE__
#define INTELLIHIDE(...) // Hide from IntelliSense
#else
#define INTELLIHIDE(...) __VA_ARGS__
#endif
So, then you could do this:
INTELLIHIDE(friend complex::complex(number);)
And also,
complex::complex(number ob)
{
INTELLIHIDE(real = ob.n;)
imaginary = 0;
}

Adding a method to an existing class to read contents of file line by line

I know that there have been many similar questions asked as this such as:
How to read line by line or a whole text file at once?
Read file line by line using ifstream in C++
However I have an already existing class with specific behaviors that I don't want to break and what I would like to do is to add an additional function to this class.
The current class I'm working on is a basic TextFileReader class and it inherits from a FileHandler class. I'll show the current class hierarchy so you can see what I already have: You can ignore the ExceptionHandler that is used as it is irrelevant to this question but I left it here as this is how my class is defined.
FileHandler.h
#pragma once
#include <string>
#include <sstream>
#include <fstream>
namespace util {
class FileHandler {
protected:
std::fstream fileStream_;
std::string filePath_;
std::string filenameWithPath_;
private:
bool saveExceptionInLog_;
public:
virtual ~FileHandler();
FileHandler(const FileHandler& c) = delete;
FileHandler& operator=(const FileHandler& c) = delete;
protected:
FileHandler(const std::string& filename, bool saveExceptionInLog);
void throwError(const std::string& message) const;
void throwError(const std::ostringstream& streamMessage) const;
};
} // namespace util
FileHandler.cpp
#include "FileHandler.h"
#include "ExceptionHandler.h"
using namespace util;
FileHandler::FileHandler(const std::string & filename, bool saveExceptionInLog) :
saveExceptionInLog_(saveExceptionInLog),
filenameWithPath_(filename) {
// Extract path info if it exists
std::string::size_type lastIndex = filename.find_last_of("/\\");
if (lastIndex != std::string::npos) {
filePath_ = filename.substr(0, lastIndex);
}
if (filename.empty()) {
throw ExceptionHandler(__FUNCTION__ + std::string(" missing filename", saveExceptionInLog_));
}
}
FileHandler::~FileHandler() {
if (fileStream_.is_open()) {
fileStream_.close();
}
}
void FileHandler::throwError(const std::string & message) const {
throw ExceptionHandler("File [" + filenameWithPath_ + "] " + message, saveExceptionInLog_);
}
void FileHandler::throwError(const std::ostringstream & streamMessage) const {
throwError(streamMessage.str());
}
TextFileReader.h
#pragma once
#include "FileHandler.h"
namespace util {
class TextFileReader : public FileHandler {
public:
explicit TextFileReader(const std::string& filename);
virtual ~TextFileReader() = default;
TextFileReader(const TextFileReader& c) = delete;
TextFileReader& operator=(const TextFileReader& c) = delete;
std::string readAll() const;
};
} // namespace util
TextFileReader.cpp
#include "TextFileReader.h"
using namespace util;
TextFileReader::TextFileReader(const std::string & filename) :
FileHandler( filename, true ) {
fileStream_.open(filenameWithPath_.c_str(), std::ios_base::in);
if (!fileStream_.is_open()) {
throwError(__FUNCTION__ + std::string(" can not open file for reading"));
}
}
std::string TextFileReader::readAll() const {
std::ostringstream stream;
stream << fileStream_.rdbuf();
return stream.str();
}
What I would like to do or what I'm trying to do is to add this method to my TextFileReader
std::vector<std::string> readLineByLine() const;
And I have tried several of the methods from the original Q/A's that I listed above at the beginning of this question.
Some of the issues that I have come into is that in the base class I'm storing a fstream object and not an ifstream or ofstream object so trying to use std::getline in a loop is not working. I was trying to read line by line directly from the filestream handle.
On my next attempt I tried to reuse the already existing readAll() and read all of the file's contents into a single buffer and return that back as a single string, then parse that string into a vector of strings. In this approach in my while loop I am still not able to use std::getline because it is using an ostringstream object and not an istringstream object.
The function should work something like this - pseudo code:
std::vector<std::string> TextFileReader::readLineByLine() const {
// get contents from file either line by line and store
// each line into a string and push that string into a
// vector of strings then return that vector after all
// lines have been read.
// or...
// read all contents from file into single string buffer and parse
// that string into a vector of strings and return that vector.
}
And this is where I'm having my issue. Any suggestions?
Edit
I had originally tried user's Bapo's approach but I was getting this compiler error:
1>------ Build started: Project: ChemLab, Configuration: Debug Win32 ------
1>TextFileReader.cpp
1>c:\...\textfilereader.cpp(24): error C2665: 'std::getline': none of the 2 overloads could convert all the argument types
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\string(160): note: could be 'std::basic_istream<char,std::char_traits<char>> &std::getline<char,std::char_traits<char>,std::allocator<char>>(std::basic_istream<char,std::char_traits<char>> &,std::basic_string<char,std::char_traits<char>,std::allocator<char>> &)'
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\string(129): note: or 'std::basic_istream<char,std::char_traits<char>> &std::getline<char,std::char_traits<char>,std::allocator<char>>(std::basic_istream<char,std::char_traits<char>> &&,std::basic_string<char,std::char_traits<char>,std::allocator<char>> &)'
1>c:\...\textfilereader.cpp(24): note: while trying to match the argument list '(const std::fstream, std::string)'
1>Done building project "ChemLab.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
However user one commented that if I made fileStream_ mutable the const function won't work. I went ahead and added the mutable modifier to fileStream_ member and now the function compiles.
You could do something as simple as this:
std::vector<std::string> TextFileReader::readLineByLine() {
std::vector<std::string> return_vector{};
std::string line;
while(std::getline(fileStream_, line)) {
return_vector.push_back(line);
}
return return_vector;
}
Though, after this, your entire stream will be read, and will be "empty"
EDIT: forgot to actually return the vector.

How to assign a unique_ptr with a custom deleter

I am trying to pass a pointer to a function that then sets a unique_ptr inside a struct to the pointer passed in. However, I get the following compile error on the last line of the function.
error C2280: 'std::unique_ptr< ALLEGRO_BITMAP,std::default_delete< ALLEGRO_BITMAP>>::unique_ptr(const std::unique_ptr< ALLEGRO_BITMAP,std::default_delete< ALLEGRO_BITMAP>> &)' : attempting to reference a deleted function
c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr< ALLEGRO_BITMAP,std::default_delete< ALLEGRO_BITMAP>>::unique_ptr'
This diagnostic occurred in the compiler generated function 'Skin::Skin(const Skin &)'
Judging from the errors I believe it has something to do with me adding the delete template for ALLEGRO_BITMAP to namespace std, but I don't know why or how to fix it.
using namespace std;
namespace std {
template<>
class default_delete < ALLEGRO_BITMAP > {
public:
void operator()(ALLEGRO_BITMAP* ptr) {
al_destroy_bitmap(ptr);
}
};
}
typedef struct {
unique_ptr<ALLEGRO_BITMAP> img;
} Skin;
typedef struct {
Skin skins[MAX_ENTITY_COUNT];
} World;
unsigned int createBlock(World world, ALLEGRO_BITMAP* img) {
unsigned int entity = newEntityIndex(world);
world.skins[entity].img = make_unique<ALLEGRO_BITMAP>(img);
return entity;
} // error on this line
Any help is appreciated. Thanks.
In your createBlock function you take World by value which means that it will be copied. However, you can't copy a unique_ptr so that is where your error comes from. This would also mean that setting the unqiue_ptr in the function wouldn't have any effect.
Instead you should take World by reference:
unsigned int createBlock(World& world, ALLEGRO_BITMAP* img) {
unsigned int entity = newEntityIndex(world);
world.skins[entity].img = make_unique<ALLEGRO_BITMAP>(img);
return entity;
}
Note that the same is true for the call to newEntityIndex and that the arguments to make_unique will be passed to the ALLEGRO_BITMAP constructor.
So what you probably want is:
world.skins[entity].img.reset(img);

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.

How can I fix my Factory Pattern to eradicate these compile errors?

My goal is to create a system wherein I can provide the string name of an class at run time and have it return an instance of that class in turn.
Searching stackoverflow, I came across an example that seems to do exactly what I am trying to accomplish, although I am currently unable to have it compile properly. The following is based on that code:
//LevelObject.h
#pragma once
#include <map>
#include <string>
class LevelObject
{
protected:
int ID;
public:
template<class T> static LevelObject* createT(void)
{
return new T(0);
}
LevelObject(void);
~LevelObject(void);
};
struct BaseFactory
{
typedef std::map<std::string, LevelObject*(*)()> map_type;
static LevelObject* createInstance(const std::string& s)
{
map_type::iterator it = getMap()->find(s);
if(it == getMap()->end())
{
return 0;
}
return it->second();
}
private:
static map_type* objectMap;
protected:
static map_type* getMap()
{
if(!objectMap)
{
objectMap= new map_type;
}
return objectMap;
}
};
template<class T>
struct DerivedRegister : BaseFactory
{
DerivedRegister(const std::string& s)
{
getMap()->insert(std::make_pair( s, &LevelObject::createT<T> ));
}
};
//Item.h
#pragma once
#include "LevelObject.h"
class Item :
public LevelObject
{
int ID;
static DerivedRegister<Item> reg;
public:
Item(int id);
~Item(void);
};
//Item.cpp
#include "Item.h"
Item::Item(int id)
{
ID = id;
}
Item::~Item(void)
{
}
DerivedRegister<Item> Item::reg("item");
The logic is that the derived objects, i.e. Item, will register a string and reference to a function that returns an instance of itself. On calling createInstance, it will take in a user inputted string and use the map to determine the object to return.
Unfortunately, this code is not compiling correctly, and gives me the following errors:
Error 1 error C2752:
'std::tr1::_Remove_reference<_Ty>' :
more than one partial specialization
matches the template argument list
Error 2 error C2528: 'abstract
declarator' : pointer to reference is
illegal c:\program files\microsoft
visual studio
10.0\vc\include\type_traits 965
Error 3 error C2528: 'type' : pointer
to reference is illegal c:\program
files\microsoft visual studio
10.0\vc\include\type_traits 349
If someone can help smooth out these errors, I would greatly appreciate it.
Or perhaps I am going about this entirely wrong in the first place, so if someone instead feels that I should be going in a different direction entirely please let me know.
Thanks in advance.
It's been a long time since this question was posted, but since there's no answer and I stumbled here too, I figured I'd add one. I copied the same factory code you did (from the StackOverflow answer here) and had the same problem. I found the solution at this StackOverflow answer.
It turns out Visual Studio 2010 (which I'm assuming you're using) has a problem with std::make_pair. Just use std::pair<std::string,LevelObject*(*)()> instead and you'll be good to go. At least that resolved this exact same problem for me.
I added empty bodies to the LevelObject class constructor and destructor:
LevelObject(void) { }
~LevelObject(void) { }
Then declared the static map member variable of the BaeFactory class:
BaseFactory::map_type* BaseFactory::map;
and the code compiled without errors in both GCC and Visual Studio.