I've been stuck on this one problem all day and maybe someone can explain it to me? I'm not providing my exact code, but a similar situation of what I'm trying to accompish (and the shortened version). It's a restaurant simulator.
int main() {
Restaurant i;
string tableID;
cin >> tableID;
i.append(new Table(tableID));//this appends a new table to the linked list
}
//.h file we're not allowed to modify
class Table
{
public:
Table(const string& tableID);//constructor
private:
string* tableID;
}
// .cpp file I'm writing
Table::Table(const string& tableID){
this->tableID = tableID;
}
I'm getting the error:
table.cc:9:18: error: cannot convert ‘const string {aka const std::__cxx11::basic_string}’ to ‘std::__cxx11::string* {aka std::__cxx11::basic_string*}’ in assignment
this->tableID = tableID;
Can anyone tell me what's going on? To me it seems like it's passing the address of tableID in main() and assigning it to a pointer in the constructor, which I thought was legal but maybe it's the const throwing me off.
Several options:
Change the definition of tableID in class Table to be string tableID. In this case you'll keep a copy of the value in the instance.
Change the assignment to this->tableID to be this->tableID = &tableID. In this case you'll assign the address of the tableID parameter to this->tableID. In this case you'll only keep a pointer to the table name in the instance, which could cause some interesting behavior. You'll probably learn the most with this approach.
Change the assignment to this->tableId = new string(tableID). Here you're allocating a new string, populating it with the value of the parameter tableID, and then assigning the address of the new string to the instance var tableID. But because you don't have a destructor defined for this class you'll leak this allocated string every time you destroy an instance to Table.
Perhaps some combination of the above would be best.
Best of luck.
Related
I found a compiler error that I can not understand why it happens only for std::map with std::unique_ptr.
Assume we have the follow unoredered map object and an iteration code for it:
std::unordered_map<uint32_t, std::shared_ptr<char>> map;
for (const std::pair<uint32_t, std::shared_ptr<char>>& item : map)
{
// do something
}
That's compiled well, but if we use unique pointer instead the shared pointer as follows, then we get a compiler error about the iteration pair type:
std::unordered_map<uint32_t, std::unique_ptr<char>> map;
for (const std::pair<uint32_t, std::unique_ptr<char>>& item : map)
{
// do something
}
error C2440: 'initializing': cannot convert from 'std::pair<const _Kty,_Ty>' to
'const std::pair<uint32_t,std::unique_ptr<char,std::default_delete<_Ty>>>
Following this error, we can just add 'const' to the key type and it is compiled.
for (const std::pair<const uint32_t, std::unique_ptr<char>>& item : map)
^^^
|||
Why is this compiling error happens just for unique pointer?
A friend gave me the answer and I'm sharing.
The answer lies in the concept of implicit conversion(copy) a compiler is allowed to do.
Lets see the follow simple example:
const char x = 4;
const char& r = x; // r is reference for x. Checking their addresses yields the same
// address.
const int& ir = c; // implicit creation of object + conversion(copy).
// ir is different type of x, therefor compiler does implicit
// conversion(copy): it creates behind the scene an object of int,
// convert x into this temporary object. The temporary int object is
// then bound to the reference ir. Checking addresses of ir and x
// yields different addresses because ir is reference of the temporary
// object, not to x
So even we use reference - planning for just pointing on an existing object,
we may actually have an object construction + copy (if the types are different and there is conversion between them).
The same happens in the loop I gave in the question:
std::unordered_map<uint32_t, std::shared_ptr<char>> map;
for (const std::pair<uint32_t, std::shared_ptr<char>>& item : map)
{
// do something
}
while the real object held by the map is of type of
std::pair<const uint32_t, std::shared_ptr<char>>
the loop uses reference of different type:
std::pair<uint32_t, std::shared_ptr<char>>
and therefor, behind the scene, for every iteration, a new temporary object is implicitly constructed and a copy operation for conversion is done.
Not only that it isn't efficient, but it also failed to be compiled when the value is unique_ptr because the conversion does copy and unique_ptr can not be copied.
Thats why using 'auto' may save you such mistakes,
std::unordered_map<uint32_t, std::shared_ptr<char>> map;
for (const auto& item : map)
{
// do something
}
I myself sometimes prefer to play and use the explicit form instead 'auto' in order to face such problems and learn :)
suppose I have a class like this and I would like to create a string with a
specific capacity. I tried doing the following but that did not work.
Any suggestions ? I know I could do it in the constructor but would like to do it during the declaration if possible.
class foo
{
std::string bar = std::string().resize(45);
}
I get the error
main.cpp: In function 'int main()':
main.cpp:8:46: error: conversion from 'void' to non-scalar type 'std::__cxx11::string {aka std::__cxx11::basic_string}' requested
std::string test = std::string().resize(45);
In C++, you probably don't want to "chain" methods unless previous methods have the correct return type.
As suggested by #James Maa, you can do simply use the constructor.
In c++11 we have new feature called move constructor so
string str = string();
doesn't cause extra time.
http://en.cppreference.com/w/cpp/language/move_constructor
with move constructor, the program would directly use the address of the temporary constructed string after = sign, without making a copy.
The problem is that resize()function in c++ actually returns void
basic_string( size_type count,
CharT ch,
const Allocator& alloc = Allocator() );
This constructor might be something you are directly interested in.
You can do something with
std::string str(45, ' ');
For example, I cannot write this:
class A
{
vector<int> v(12, 1);
};
I can only write this:
class A
{
vector<int> v1{ 12, 1 };
vector<int> v2 = vector<int>(12, 1);
};
Why is there a difference between these two declaration syntaxes?
The rationale behind this choice is explicitly mentioned in the related proposal for non static data member initializers :
An issue raised in Kona regarding scope of identifiers:
During discussion in the Core Working Group at the September ’07 meeting in Kona, a question arose about the scope of identifiers in the initializer. Do we want to allow class scope with the possibility of forward lookup; or do we want to require that the initializers be well-defined at the point that they’re parsed?
What’s desired:
The motivation for class-scope lookup is that we’d like to be able to put anything in a non-static data member’s initializer that we could put in a mem-initializer without significantly changing the semantics (modulo direct initialization vs. copy initialization):
int x();
struct S {
int i;
S() : i(x()) {} // currently well-formed, uses S::x()
// ...
static int x();
};
struct T {
int i = x(); // should use T::x(), ::x() would be a surprise
// ...
static int x();
};
Problem 1:
Unfortunately, this makes initializers of the “( expression-list )” form ambiguous at the time that the declaration is being parsed:
struct S {
int i(x); // data member with initializer
// ...
static int x;
};
struct T {
int i(x); // member function declaration
// ...
typedef int x;
};
One possible solution is to rely on the existing rule that, if a declaration could be an object or a function, then it’s a function:
struct S {
int i(j); // ill-formed...parsed as a member function,
// type j looked up but not found
// ...
static int j;
};
A similar solution would be to apply another existing rule, currently used only in templates, that if T could be a type or something else, then it’s something else; and we can use “typename” if we really mean a type:
struct S {
int i(x); // unabmiguously a data member
int j(typename y); // unabmiguously a member function
};
Both of those solutions introduce subtleties that are likely to be misunderstood by many users (as evidenced by the many questions on comp.lang.c++ about why “int i();” at block scope doesn’t declare a default-initialized int).
The solution proposed in this paper is to allow only initializers of the “= initializer-clause” and “{ initializer-list }” forms. That solves the ambiguity problem in most cases, for example:
HashingFunction hash_algorithm{"MD5"};
Here, we could not use the = form because HasningFunction’s constructor is explicit.
In especially tricky cases, a type might have to be mentioned twice. Consider:
vector<int> x = 3; // error: the constructor taking an int is explicit
vector<int> x(3); // three elements default-initialized
vector<int> x{3}; // one element with the value 3
In that case, we have to chose between the two alternatives by using the appropriate notation:
vector<int> x = vector<int>(3); // rather than vector<int> x(3);
vector<int> x{3}; // one element with the value 3
Problem 2:
Another issue is that, because we propose no change to the rules for initializing static data members, adding the static keyword could make a well-formed initializer ill-formed:
struct S {
const int i = f(); // well-formed with forward lookup
static const int j = f(); // always ill-formed for statics
// ...
constexpr static int f() { return 0; }
};
Problem 3:
A third issue is that class-scope lookup could turn a compile-time error into a run-time error:
struct S {
int i = j; // ill-formed without forward lookup, undefined behavior with
int j = 3;
};
(Unless caught by the compiler, i might be intialized with the undefined value of j.)
The proposal:
CWG had a 6-to-3 straw poll in Kona in favor of class-scope lookup; and that is what this paper proposes, with initializers for non-static data members limited to the “= initializer-clause” and “{ initializer-list }” forms.
We believe:
Problem 1: This problem does not occur as we don’t propose the () notation. The = and {} initializer notations do not suffer from this problem.
Problem 2: adding the static keyword makes a number of differences, this being the least of them.
Problem 3: this is not a new problem, but is the same order-of-initialization problem that already exists with constructor initializers.
One possible reason is that allowing parentheses would lead us back to the most vexing parse in no time. Consider the two types below:
struct foo {};
struct bar
{
bar(foo const&) {}
};
Now, you have a data member of type bar that you want to initialize, so you define it as
struct A
{
bar B(foo());
};
But what you've done above is declare a function named B that returns a bar object by value, and takes a single argument that's a function having the signature foo() (returns a foo and doesn't take any arguments).
Judging by the number and frequency of questions asked on StackOverflow that deal with this issue, this is something most C++ programmers find surprising and unintuitive. Adding the new brace-or-equal-initializer syntax was a chance to avoid this ambiguity and start with a clean slate, which is likely the reason the C++ committee chose to do so.
bar B{foo{}};
bar B = foo();
Both lines above declare an object named B of type bar, as expected.
Aside from the guesswork above, I'd like to point out that you're doing two vastly different things in your example above.
vector<int> v1{ 12, 1 };
vector<int> v2 = vector<int>(12, 1);
The first line initializes v1 to a vector that contains two elements, 12 and 1. The second creates a vector v2 that contains 12 elements, each initialized to 1.
Be careful of this rule - if a type defines a constructor that takes an initializer_list<T>, then that constructor is always considered first when the initializer for the type is a braced-init-list. The other constructors will be considered only if the one taking the initializer_list is not viable.
I'm looking for a way of checking whether a std::function pointer is bound to a member function of a particular object. I'm aware that std::function itself has no '==' operator. I have however come across the std::function::target method which should be able, in principle, to give me the address of the function to which the pointer is pointing. My starting point was therefore this:
bool MyClass::isThePointerSetToMyMethod(std::function<void (const char*, string)> const& candidate)
{
// Create a pointer to the local reportFileError function using the same syntax that we did in the constructor:
std::function<void (const char *, string)> localFn = std::bind(&MyClass::theLocalMember, this,
std::placeholders::_1, std::placeholders::_2);
// Find the target
auto ptr1 = localFn.target< std::function<void (const char *, string)> >();
// Find the target of the candidate
auto ptr2 = candidate.target< std::function<void (const char *, string)> >();
// Compare the two pointers to see whether they actually point to the same function:
if (!ptr1 || !ptr2) return false;
if (*ptr1 == *ptr2)
return true;
else
return false;
}
This doesn't work, and the reason is that the values of 'ptr1' and 'ptr2' are always returned as null. According to the documentation for the std::function::target method, this must be because the type that I've specified for the target is not correct.
If I look at what target_type(localFn) actually is (using Visual C++ 2013), it's a bit frightening:
class std::_Bind<1,void,struct std::_Pmf_wrap<void (__thiscall MyClass::*)(char const *, string),void,class MyClass,char const *,string>,class MyClass * const,class std::_Ph<1> &,class std::_Ph<2> &>
Nevertheless, target_type(candidate) gives the same result, so I thought I'd try a typedef:
bool MyClass::isThePointerSetToMyMethod(std::function<void (const char*, string)> const& candidate)
{
typedef class std::_Bind<1,void,struct std::_Pmf_wrap<void (__thiscall MyClass::*)(char const *, string),void,class MyClass,char const *,string>,class MyClass * const,class std::_Ph<1> &,class std::_Ph<2> &> wally;
// Create a pointer to the local reportFileError function using the same syntax that we did in the constructor:
std::function<void (const char *, string)> localFn = std::bind(&MyClass::theLocalMember, this,
std::placeholders::_1, std::placeholders::_2);
// Find the target
auto ptr1 = localFn.target< wally >();
// Find the target of the candidate
auto ptr2 = candidate.target< wally >();
// Compare the two pointers to see whether they actually point to the same function:
if (!ptr1 || !ptr2) return false;
if (*ptr1 == *ptr2)
return true;
else
return false;
}
Alas this gets me no further; the values of ptr1 and ptr2 are still null.
So for now I've run out of ideas. Is there anyone reading this who knows either:
(1) The appropriate form for a typedef for a std::function pointer to the member function of a class, or
(2) A better way to achieve my ultimate objective, which is to tell whether a std::function pointer is pointing to a particular object's member function or whether it isn't?
[Background, in case anyone is interested: the reason I'm doing this is that I have a callback table where different callbacks are set to different functions depending on the state that the system is in; this makes state control very simple, as it means that in a given context I can call a given callback and know that the actions taken by the function I've called will be appropriate for the current state, without having to know anything about what that state actually is. Usually, when an object is instantiated which will change the system state, it takes control of the relevant callback(s) and binds them to whatever local member functions are appropriate for whatever state it's in. Under these circumstances, however, the object's destructor ought to return the callbacks to their status quo ante so that they are not left pointing to nothing.
Very rarely, an object may bind the callbacks to its member functions in its constructor, but before its destructor is called another object may take control of the same callbacks itself, and re-bind them to member functions of its own. If this happens, then the first object's destructor needs to be able to recognise that this has happened, and exit without affecting the callbacks' assignment to the second object's methods. The obvious way to do this is for the destructor to be able to check whether the callbacks are still assigned to its own methods or not, and if they are not then to leave well alone.]
Flesh out the callback table into a class which manages the table. All modifications to the table should be done through this class's interface. Internally, you would maintain a stack-like structure which lets you undo the changes done to the callback table. Barebones interface would look something like:
class CallbackTable
{
public:
bool ApplyChanges(...)
{
//Push the old values of the entries that would be changed here into your change-tracker stack and modify the table
}
bool UnApplyChanges(...)
{
//Pop the change-tracker stack and restore the table to the state it was in before the most recent change was applied.
}
};
I'm looking into move semantics from C++11 and I'm curious how to move fundamental types like boolean, integer float etc. in the constructor. Also the compound types like std::string.
Take the following class for example:
class Test
{
public:
// Default.
Test()
: m_Name("default"), m_Tested(true), m_Times(1), m_Grade('B')
{
// Starting up...
}
Test(const Test& other)
: m_Name(other.m_Name), m_Times(other.m_Times)
, m_Grade(other.m_Grade), m_Tested(other.m_Tested)
{
// Duplicating...
}
Test(Test&& other)
: m_Name(std::move(other.m_Name)) // Is this correct?
{
// Moving...
m_Tested = other.m_Tested; // I want to move not copy.
m_Times = other.m_Times; // I want to move not copy.
m_Grade = other.m_Grade; // I want to move not copy.
}
~Test()
{
// Shutting down....
}
private:
std::string m_Name;
bool m_Tested;
int m_Times;
char m_Grade;
};
How do I move (not copy) m_Tested, m_Times, m_Grade. And is m_Name moved correctly? Thank you for your time.
Initialization and assignment of a primitive from a prvalue or xvalue primitive has exactly the same effect as initialization or assignment from a lvalue primitive; the value is copied and the source object is unaffected.
In other words, you can use std::move but it won't make any difference.
If you want to change the value of the source object (to 0, say) you'll have to do that yourself.
Looks correct. Except simple data types like bool, int, char are only copied. The point of "moving" a string is that it has a buffer that it normally has to copy when constructing a new object, however when moving the old buffer is used (copying the pointer and not the contents of the buffer).
Test(Test&& other)
: m_Name(std::move(other.m_Name)), m_Times(other.m_Times)
, m_Grade(other.m_Grade), m_Tested(other.m_Tested)
{}