I am new in C++. I have a question like whether we could define a rvalue references to null?
class Foo { };
Foo&& foo = nullptr;
I got the error:
reference to type 'Foo' could not bind to an rvalue of type 'nullptr_t'
I have a question like whether we could define a rvalue references to null?
The standard (working draft) says that no, it's not possible (emphasis mine):
A reference shall be initialized to refer to a valid object or function. [ Note: In particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by indirection through a null pointer, which causes undefined behavior.
It applies both to lvalue and rvalue references. See this bullet for more details:
Except where explicitly noted, they are semantically equivalent and commonly referred to as references.
Related
I have a custom Dialog class (derived from wxDialog). I want to add a setter so you can set a call back function MyDialog::m_f with some function of type std::function<bool(wxString&)>.
Later, the dialog will call this function.
I want to be able to pass in a lambda function (otherwise I could solve my problem with ordinary function pointers).
It must also be possible to call this setter multiple times, the last set value for m_f should be valid, thus erasing any previous set values (the value being a new function).
But, if I declare the member m_f, does it have to be initialized in the initializer list in the constructor?
For my use case that would not really work. I have to be able to set MyDialog::m_f after the dialog has been constructed (but before ShowModal is called).
Should my member m_f be a (unique) pointer to a std::function<bool(wxString&)>, so it can be set to nullptr in MyDialog::MyDialog?
My basic problem is I do not fully understand std::function. How can you make a variable of some std::function<...> type and assign a value (concrete function) to it later? What does it mean to have a variable like described which is uninitialized? How can I test whether it is (un)assigned? Is it at all possible to delay this assignment, that is: have a separate declaration and later initialization, or should a variable of std::function<...> be initialized immediately (like a const or reference)?
Thanks for any help.
BTW, the language is C++11 and we can't upgrade due to restrictions at work.
How can you make a variable of some std::function<...> type and assign a value (concrete function) to it later?
std::function has a default constructor that results in an "empty" instance. In your case, just declare the data member std::function<...> m_f and don't explicitly initialize it.
What does it mean to have a variable like described which is uninitialized?
That depends on the type of the variable. In the std::function, it's simply unusable. If you try to inoke an empty std::function, and exception will be thrown.
How can I test whether it is (un)assigned?
std::function has an explicit conversion operator to bool. It evaluates to true when the object is non-empty, i.e.
if (m_f)
m_f(/* parameters... */);
else
; // do nothing, not set yet
How can you make a variable of some std::function<...> type and assign a value (concrete function) to it later?
If you want to later assign lambda expression to the function object through a setter, you can turn this member function into a template, e.g.
template<class Fct>
void setCallback(Fct&& f)
{
m_f = std::forward<Fct>(f);
}
Another option is to pass a std::function with the desired signature to a non-template member function.
The thing is, 4th edition of C++ Programming language says:
In this particular case, if you forgot to delete a copy or move operation, no harm is done. A
move operation is not implicitly generated for a class where the user has explicitly declared a destructor.
Furthermore, the generation of copy operations is deprecated in this case (§44.2.3). This
can be a good reason to explicitly define a destructor even where the compiler would have implicitly
provided one (§17.2.3).
I've tried this code:
#include <iostream>
class Foo {
public:
~Foo() {}
}
int main() {
Foo x;
Foo y(x);
return 0;
}
and there is no errors and exeptions here. I know that copy constructor should be generated implicitly in c++98, but 4th says that copy is deprecated. What does it mean?
My understanding is that an implicitly-declared constructor is not necessary implicitly-defined.
From cppreference :
Implicitly-declared copy constructor
If no user-defined copy constructors are provided for a class type (struct, class, or union), the compiler will always declare a copy constructor as a non-explicit inline public member of its class.
Implicitly-defined copy constructor
If the implicitly-declared copy constructor is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used.
The generation of the implicitly-defined copy constructor is deprecated if T has a user-defined destructor or user-defined copy assignment operator.
So in your case, the copy constructor is implicitly-declared but not implicitly-defined if not odr-used, which basically means it is not defined unless required somewhere.
See also : What is the distinction between implicitly-declared and implicitly-defined copy constructors?
The question titles says it all. I need to know if the default copy/move assignment/ctors implemented implicitly by the compiler are declared noexcept.
The standard says:
An inheriting constructor (12.9) and an implicitly declared special
member function (Clause 12) have an exception-specification. If f is
an inheriting constructor or an implicitly declared default
constructor, copy constructor, move constructor, destructor, copy
assignment operator, or move assignment operator, its implicit
exception-specification specifies the type-id T if and only if T is
allowed by the exception-specification of a function directly invoked
by f’s implicit definition; f allows all exceptions if any function it
directly invokes allows all exceptions, and f has the
exception-specification noexcept(true) if every function it directly
invokes allows no exceptions.
So if the implicitly declared copy/move assignment/ctors of your class do not need to call anything that is marked noexcept(false) then they will have the noexcept(true) specifier. The functions that need to be called will be the copy/move assignment/ctors of base class and non-static data members.
Obviously they can't just be unconditionally noexcept, that would be both silly and wrong (for example, the implicit copy constructor for a class containing a std::string member might need to allocate memory, so it can't sensibly be noexcept).
They're noexcept if they only call functions that are noexcept, and they're not noexcept if they call any functions that are not noexcept.
I want to understand move semantics and rvalue reference and the object state after the function call.
For example: I expect that caller fills the list and gets to the constructor argument:
typedef std::list<int> IntList;
class IntHolder {
public:
explicit IntHolder(IntList&& l)
: m_h(l)
{}
private:
IntList m_h;
};
IntList a;
a.push_back(1);
IntHolder holder(a);
// ... is 'a' guaranteed empty (not empty) here?
a is guaranteed to not be empty, because it was never passed as an rvalue reference: it is a declared variable, not a compiler generated temporary, and hence cannot be passed as an rvalue reference.
What's happening here is that a temporary IntList gets copy-constructed from a, and that temporary is passed to your constructor. a itself remains intact.
To make things really complicated: even that temporary is not moved! When you use an rvalue reference, it decays to a normal reference, which happens when you say m_h(l) in your initializer list. If it were otherwise, you would not be able to access l from within your constructor. So, the temporary is copied a second time. You can enforce move semantics by replacing m_h(l) with m_h(std::move(l)).
Whenever you try to invoke move semantics, what happens depends on how the class you are using is written. Thus, there are no language guarantees. The only thing a move constructor needs to make sure is that the destructor will not mess up when it is run. It is simply an error to access an object in any way after invoking move semantics on it.
I have C++/CLI class that defines a property:
public ref class AbstractOffer
{
public:
AbstractOffer();
property String^ Body;
};
In some function the AbstractOffer class is passed by const ref
foo(const AbstractOffer^ ao)
{
ao->Body;
}
When I call the property the method compiler gives the following error :-
error C2662: 'ivrworx::interop::AbstractOffer::Body::get' : cannot
convert 'this' pointer from 'const ivrworx::interop::AbstractOffer'
to 'ivrworx::interop::AbstractOffer %' 1> Conversion loses
qualifiers
It seems somehow connected to const. How can I call the Body property of the object if the object reference is passed by const?
The const qualifier is a problem in C++/CLI. It is only meaningful when it can be checked and that's not in general possible in .NET. It is of course not a problem when you only have one kind of compiler and that compiler follows strict language rules. Like C++. But .NET supports many languages, your method could be easily called from a Cobol.NET program for example. The odds of ever getting const-correctness added to the Cobol language are zero.
The compiler does compile code with const qualifiers and does make an effort to check when it can. Which is why you got the diagnostic. That can even work when the declaration exists in another assembly, as long as it was compiled with C++/CLI, the compiler emits modopt annotations in the metadata.
But there are limitations with that. Properties are one of them, you can't add the const qualifier to the getter, or a member function in general, you'll get slapped with C3842.
Best thing to do is to use C++/CLI for what it is good at, it is an interop language. And const qualifiers just don't work well in an interop scenario.
The only way I know to get round this is the cast away the const-ness. As long as you don't modify the object, it should be fine. (If you do modify it, I've no idea what the outcome will be).
i.e. change your function to be
void foo(const AbstractOffer^ ao)
{
const_cast<AbstractOffer^>(ao)->Body;
}