delete modifier vs declaring function as private - c++

I read this question, but it still doesn't make a lot of sense to me. It still sounds more like a sugarcoating feature.
What's the difference between:
class A
{
// public/private ?
A (const A&) = delete;
};
and
class A
{
private:
A (const A&); // MISSING implementation
};
Same for operator= or other functions.

One difference is that =delete allows for compile-time errors while in some cases the declaration without a definition is only caught at link-time (at which the error message is typically not pointing you to the source of the problem). One such case is when you add a member function that tries to copy an instance of A. Even when it's not a member function of A, the error message about the copy-ctor being private is not as clear as using =delete.
To avoid confusion, I'd recommend you make the deleted function public as otherwise you will get additional and misleading error messages.

The difference is that the purpose of the =delete code is explicit in it's purpose. Declaring functions as private / inaccessible was a trick. Although most people knew it, the error it generated was obscure (a linking/access level error instead of a semantical problem in the code - i.e. "you are using a deleted function").

One difference is that the old-fashioned form gives undefined behaviour if the class (or a friend) tries to destroy itself. Within class members and friends, the destructor is accessible, so there is no compile-time error if it's used. Instead, you get a violation of the One Definition Rule. In practice, this will cause a link error, but formally the behaviour is undefined.
Deleting the constructor (or other function) causes a compile error if the function is needed in any circumstances; and states the intent more explicitly, allowing the compiler to give better diagnostic messages. This is especially useful when functions are implicitly deleted due to something else being deleted.

Another thing which hasn't been mentioned yet: when inheriting / overriding, you can't =delete a function which already has a body but you can change a public function into a private one, making it basically inaccessible from outside.

Related

Can copy-constructor with delete qualifier be private? [duplicate]

In order to make an object non-copiable we can explicitly delete both its copy-constructor and copy-assignment operator.
My question is: What is the right place to do it - in the public, private or protected section of the class? And - does this choice make any difference?
what is the right place to do it - in the public, private or protected section of the class?
I would put them in the public section.
This is because deleting a constructor or an assignment operator is orthogonal to making them private / protected; and when these aren't deleted, they are public by default. Putting the deletions in one of those two sections seems to me like hinting "If I hadn't deleted them, I would have made them private/protected" - which is not a message you want to convey in your case.
Note, though, that the compiler doesn't care which section you put the deletion in.
Does where we put the deleted definition make any difference?
From a pure language standpoint it makes absolutely zero difference. Name lookup and overload resolution happen before access checking. And attempting to refer to a deleted function at the end of overload resolution makes your program ill-formed, period. A compiler may or may not issue another diagnostic about the accessibility, but the program already has an error that must be reported.
So you can put that deleted definition with whatever accessibility you desire. I think most will keep it private, to be inline with the "old" practice of making a class non-copyable (put the declaration of those members in the private section of the class, and not define them), if only to help those who know the old ways "get it" sooner. A mixture of idioms, if you would.
Marking as private is also something you can't avoid if you need to support both C++03 and C++11 mode. With the help of a macro, a header can be made to conform to both standards easily:
#if __cplusplus >= 201103L
#define DELETED_DEFINITION = delete
#else
#define DELETED_DEFINITION
#endif
class noncopyable {
private:
// This header can be compiled as both C++11 and C++03
noncopyable(noncopyable const&) DELETED_DEFINITION;
void operator=(noncopyable const&) DELETED_DEFINITION;
};
From Scott Meyers's book, Effective Modern C++ (Item 10), it seems that it is better to define them as public:
By convention, deleted functions are declared public, not private.
There’s a reason for that. When client code tries to use a member
function, C++ checks accessibility before deleted status. When client
code tries to use a deleted private function, some compilers complain
only about the function being private, even though the function’s
accessibility doesn’t really affect whether it can be used. It’s worth
bearing this in mind when revising legacy code to replace
private-and-not-defined member functions with deleted ones, because
making the new functions public will generally result in better error
messages.
In addition, I believe that a deleted copy constructor/assignment, should be part of the class interface to be shared with ALL of the class users. Such kind of information should not be kept as secret by making them private.
delete works just as well with private access.
The effect of delete is to cause an error if the function is chosen by overload resolution.
The effect of private is to cause an error if the function is chosen by overload resolution from outside the class or its friends.
If both errors apply, the ultimate outcome is the same either way, but public might help avoid compiler messages about access privileges, which could cause confusion.
The access of a deleted function is irrelevant. In fact, for class members, it would have made more sense to add an additional access specifier (delete:). I suspect the reason they didn't do that, was that it wouldn't work for non-member functions.
For things like the copy constructor, it makes more sense stylistically to put it in the public section. The fact that a class doesn't have a copy constructor is a pretty major fact to know about the interface to the class.
For internal functions where you are declaring a particular overload as deleted in order to get compiler-time detection of an error, it makes sense to declare the function in the same section as all the other overloads.

Question on predefined meanings for operators

In "The C++ programming language", at page 265, the author makes the following statement:
Because of historical accident, the operators = (assignment), & (address-of), and , (sequencing;
§6.2.2) have predefined meanings when applied to class objects. These predefined meanings can
be made inaccessible to general users by making them private:
Then the following example is given:
class X {
private:
void operator=(const X&);
void operator&();
void operator,(const X&);
// ...
};
void f(X a, X b)
{
a = b; // error: operator= private
&a; // error: operator& private
a,b; // error: operator, private
}
I can't quite understand what do these "error" comments refer to? Does that mean I should not define a function like f, or that all of the =, &, and , operators should be used according to the default way, and it is not necessary to redefine them?
This example simply shows a way to prevent yourself or other developers of the code from using operators, which can be used without having been defined in the class, because they're automatically generated (and have default meanings for the operations they represent).
The author of the example meant, that if you try to assign b to a (in line a = b) it will cause an error, because the assignment operator is private in the class definition.
Similar error occurs in case of address-of in the second line, and the comma operator in the third.
Making default operators/constructors private if you know they're not supposed to be used (or haven't been implemented yet) is good, because one may accidentally use a very frequent operator like assignment or copy-constructor, being unaware that it's default behavior conflicts with the class lifecycle. If such operator or constructor is made private at the very beginning of class design, the compiler will generate a compile-time error instead of performing a potentially dangerous operation without notice if the programmer accidentally uses the method.
Think default assignment operator and member pointer: it will copy the pointer whereas you might want the object to be the owner of data. Then, after someone assigns one object to another without knowing that assignment is not implemented, you will end up with a double free error. Instead of that, if the operator is private, you'll get a nice error and the code will not even compile, and you'll know what's going on.
The author intends to point out here that the operators =, & and , are usually implicitly available for a class.
So if you don't want your objects to be operated on through them then you declare them as private thus disallowing their use.
Since they are declared as private you cannot access them anymore outside the class and the compiler gives you a compilation error. The function is an example showing that.
Providing your own implementation of any operator is basically the same as implementing a class method. Operators and methods are the same in terms of accessibility. What you do is disallowing access to operators from the caller's code.
It's absolutely the same as if you defined a private method and then tried to call it from some code that is not part of your class. Just make the operators public and errors will go away.
It basically prevents any one from making an 'X' object and using the "=", "&", and "," operators on that class. Because the author of the class may implement those objects with a meaning that is quite different to what the consumer of the class might think they do ... so its best to prevent them being used at all in the case of ambiguity.
The function f is an example of a user trying to use the private operators. It shows you what code it is that you're preventing by making them private. The comment // error means that a program that contained that line would fail to compile for the stated reason.
Before discussing the error, a key here is to understand that these operations will be implicitly made available for your class. This is the essence of Scott Meyers' advice "Know what functions C++ silently writes and calls."
C++ will automatically implement the assignment operator for your class, but it may not be done correctly (for example, if your class contains a pointer member variable). By defining the assignment operator explicitly, you are telling the compiler to use your implementation instead of generating one for you. And by making it private, you are essentially disallowing assignment of one class instance to another. Anywhere you try to do this in your code, the compiler will complain, which is a good thing if you really don't want assignment to be done.
In function f the author is showing you that these statements will not compile because of how the operators are defined in the class. It is perfectly acceptable to redefine operators for your class, and sometimes it is definitely required (for example, to implement a deep copy of a pointer member variable in your class). The point of the example is to show that a) you can provide your own implementation of these operators for your class, and b) because of this you have control over whether the operators are supported and implemented correctly for your class.

error: use of deleted function

I've been working on some C++ code that a friend has written and I get the following error that I have never seen before when compiling with gcc4.6:
error: use of deleted function
‘GameFSM_<std::array<C, 2ul> >::hdealt::hdealt()’ is implicitly deleted because the default definition would be ill-formed:
uninitialized non-static const member ‘const h_t FlopPokerGameFSM_<std::array<C, 2ul> >::hdealt::h’
Edit: This comes from a part of the code using boost MSM: Boost Webpage
Edit2: There is no = delete() used anywhere in the sourcecode.
Generally speaking, what does this error mean? What should I be looking for when this type of error occurs?
The error message clearly says that the default constructor has been deleted implicitly. It even says why: the class contains a non-static, const variable, which would not be initialized by the default ctor.
class X {
const int x;
};
Since X::x is const, it must be initialized -- but a default ctor wouldn't normally initialize it (because it's a POD type). Therefore, to get a default ctor, you need to define one yourself (and it must initialize x). You can get the same kind of situation with a member that's a reference:
class X {
whatever &x;
};
It's probably worth noting that both of these will also disable implicit creation of an assignment operator as well, for essentially the same reason. The implicit assignment operator normally does members-wise assignment, but with a const member or reference member, it can't do that because the member can't be assigned. To make assignment work, you need to write your own assignment operator.
This is why a const member should typically be static -- when you do an assignment, you can't assign the const member anyway. In a typical case all your instances are going to have the same value so they might as well share access to a single variable instead of having lots of copies of a variable that will all have the same value.
It is possible, of course, to create instances with different values though -- you (for example) pass a value when you create the object, so two different objects can have two different values. If, however, you try to do something like swapping them, the const member will retain its original value instead of being swapped.
You are using a function, which is marked as deleted.
Eg:
int doSomething( int ) = delete;
The =delete is a new feature of C++0x. It means the compiler should immediately stop compiling and complain "this function is deleted" once the user use such function.
If you see this error, you should check the function declaration for =delete.
To know more about this new feature introduced in C++0x, check this out.
I encountered this error when inheriting from an abstract class and not implementing all of the pure virtual methods in my subclass.
gcc 4.6 supports a new feature of deleted functions, where you can write
hdealt() = delete;
to disable the default constructor.
Here the compiler has obviously seen that a default constructor can not be generated, and =delete'd it for you.
In the current C++0x standard you can explicitly disable default constructors with the delete syntax, e.g.
MyClass() = delete;
Gcc 4.6 is the first version to support this syntax, so maybe that is the problem...
Switching from gcc 4.6 to gcc 4.8 resolved this for me.

Opt-out of copy constructor

This might be a silly question, but...
I've been writing a number of classes that utilize non-copyable members. These classes are never initialized via the copy constructor in my source. When I try to compile without supplying my own copy-constructor, g++ throws out many errors about how it can't build a default copy constructor, due to the non-copyable member objects.
Is there a way to tell the compiler to just not give me a copy constructor?
EDIT: Yeah... feels silly... I had a case where I was invoking the copy-constructor by accident in a boost::bind call. Lesson learned.
The usual way to make things noncopyable is to declare but not define a copy constructor, and make it private so nothing can call it.
The next revision of the language will provide an explicit way to suppress these generated functions.
If you don't actually cause the copy-constructor to be called then it is not an error if the compiler would be unable to generate one. It sounds like you are (possibly indirectly) causing the copy-constructor to be used.
You can suppress the compiler generated one by declaring your own copy-constructor (you don't need to define it if you're not using it). You can place it in the private section of your class.
If this changes the error to say that the copy-constructor is inaccessible or you get link errors then you really are causing the copy-construtor to be used and you need to analyze why this is.
Not in the current version of C++. In C++ 0x, there will be an =delete; syntax to tell it that you don't want one of the special member functions the compiler will generate by default if you don't defined one yourself.
Until the new C++ 0x standard is fully supported, the best you can do is to delclare a version of the special member function, but not implement them. Normally they are made private (to help make it clear that they shouldn't be used).
Class foo
{
// ... rest of definition
private:
foo (const foo& rhs); // Do Not Implement
const foo& operator= (const foo& rhs); // Do Not Implement
};
No :)
If you want your class to be non-copyable use something like boost::noncopyable
class MyClass : private boost::noncopyable
{
}
or use a parametrizied macro in your class definition that declares a private copy constructor.

How to generate a compiler warning/error when object sliced

I want to know if it is possible to let compiler issue a warning/error for code as following:
Note:
1. Yea, it is bad programming style and we should avoid such cases - but we are dealing with legacy code and hope compiler can help identify such cases for us.)
2. I prefer a compiler option (VC++) to disable or enable object slicing, if there is any.
class Base{};
class Derived: public Base{};
void Func(Base)
{
}
//void Func(Derived)
//{
//
//}
//main
Func(Derived());
Here if I comment out the second function, the first function would be called - and the compiler (both VC++ and Gcc) feels comfortable with that.
Is it C++ standard? and can I ask compiler (VC++) to give me a warning when met such code?
Thanks so much!!!
Edit:
Thanks all so much for your help!
I can't find a compiler option to give a error/warning - I even posted this in MSDN forum for VC++ compiler consultant with no answer. So I am afraid neither gcc nor vc++ implemented this feature.
So add constructor which take derived classes as paramter would be the best solution for now.
Edit
I have submit a feedbak to MS and hope they will fix it soon:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=421579
-Baiyan
If you can modify the base class you could do something like:
class Base
{
public:
// not implemented will cause a link error
Base(const Derived &d);
const Base &operator=(const Derived &rhs);
};
Depending on your compiler that should get you the translation unit, and maybe the function where the slicing is happening.
As a variation of Andrew Khosravian's answer, I'll suggest using templated copy constructors and assignment operators. This way you don't need to know all the derived classes of a given base class in order to safeguard that base class against slicing:
class Base
{
private: // To force a compile error for non-friends (thanks bk1e)
// Not implemented, so will cause a link error for friends
template<typename T> Base(T const& d);
template<typename T> Base const& operator=(T const& rhs);
public:
// You now need to provide a copy ctor and assignment operator for Base
Base(Base const& d) { /* Initialise *this from d */ }
Base const& operator=(Base const& rhs) { /* Copy d to *this */ }
};
Although this reduces the amount of work needed, with this approach you still need to mess with each base class in order to safeguard it. Also, it will cause problems if there are legitimate conversions from Base to SomeOtherClass that employ an operator Base() member of SomeOtherClass. (In that case, a more elaborate solution involving boost::disable_if<is_same<T, SomeOtherClass> > can be used.) In any case, you should remove this code once you've identified all instances of object slicing.
To the compiler implementors of the world: Testing for object slicing is definitely something that would be worthwhile creating (optional) warnings for! I can't think of one instance where it would be desired behaviour, and it's very commonly seen in newbie C++ code.
[EDIT 27/3/2015:] As pointed out by Matt McNab, you actually don't need to declare the copy constructor and assignment operator explicitly as I've done above, as they will still be implicitly declared by the compiler. In the 2003 C++ standard, this is explicitly mentioned in footnote 106 under 12.8/2:
Because a template constructor is never a copy constructor, the presence of such a template does not suppress the implicit declaration of a copy constructor. Template constructors participate in overload resolution with other constructors, including copy constructors, and a template constructor may be used to copy an object if it provides a better match than other constructors.
I would suggest adding a constructor to your base class which takes a const reference to the derived class explicitly (with a forward declaration). In my simple test app, this constructor gets called in the slicing case. You could then at least get a run-time assertion, and you could probably get a compile-time assertion with clever use of templates (eg: instantiate a template in a way which generates a compile-time assertion in that constructor). There may also be compiler-specific ways to get compile time warnings or errors when you call explicit functions; for example, you can use "__declspec(deprecated)" for the "slice constructor" in Visual Studio to get a compile-time warning, at least in the function-call case.
So in your example, the code would look like this (for Visual Studio):
class Base { ...
__declspec(deprecated) Base( const Derived& oOther )
{
// Static assert here if possible...
}
...
This works in my test (compile-time warning). Note that it doesn't solve the copy case, but a similarly-constructed assignment operator should do the trick there.
Hope this helps. :)
The best way to combat this problem is usually to follow Scott Meyer's recommendation (see Effective C++) of only having concrete classes at the leaf nodes of your inheritance tree and ensuring that non-leaf classes are abstract by having at least one pure virtual function (the destructor, if nothing else).
It is surprising how often this approach helps clarify the design in other ways, as well. The effort of isolating a common abstract interface is usually a worthwhile design effort in any case.
Edit
Although I originally didn't make this clear, my answer comes from the fact that it is not possible to warn accurately about object slicing at compile time and for this reason it can lead to a false sense of security if you have a compile time assertion, or a compiler warning enabled. If you need to find out about instances of object slicing and need to correct them then it implies that you have the desire and ability to change the legacy code. If this is the case, then I believe that you should seriously consider refactoring the class hierarchy as a way of making the code more robust.
My reasoning is this.
Consider some library code that defines a class Concrete1 and uses it in the inferface to this function.
void do_something( const Concrete1& c );
Passing the type be reference is for efficiency and is, in general, a good idea. If the library considers Concrete1 to be a value type the implementation may decided to make a copy of the input parameter.
void do_something( const Concrete1& c )
{
// ...
some_storage.push_back( c );
// ...
}
If the object type of the passed reference is, indeed, Concrete1 and not some other derived type then this code is fine, no slicing is performed. A general warning on this push_back function invocation might produce only false positives and would most likely be unhelpful.
Consider some client code that derives Concrete2 from Concrete1 and passes it into another function.
void do_something_else( const Concrete1& c );
Because the parameter is taken by reference no slicing occurs here on the parameter to check, so it would not be correct to warn here of slicing as it may be that no slicing occurs. Passing in a derived type to a function that takes a reference or pointer is a common and useful way to take advantage of polymorphic types so warning or disallowing this would seem counter-productive.
So where is there error? Well the 'mistake' is passing in a reference to something that is derived from a class that is then treated as though it is a value type by the called function.
There is, in general, no way to generate a consistently useful compile time warning against object slicing and this is why the best defence, where possible, is to eliminate the problem by design.
This is commonly called Object Slicing and is a well-known enough problem to have its own Wikipedia article (although it is only a short description of the problem).
I believe I have used a compiler that had a warning you could enable to detect and warn about this. However, I don't recall which one that was.
Not really a solution to your immediate problem, but....
Most functions that take class/struct objects as parameters should declare the parameters to be of type "const X&" or "X&", unless they have a very good reason not to.
If you always do this, object slicing will never be a problem (references don't get sliced!).
class Derived: public Base{};
You're saying Derived IS a Base, and so it should work in any function that takes a base. If this is a real problem, maybe inheritance isn't what you really want to be using.
I modified your code slightly:
class Base{
public:
Base() {}
explicit Base(const Base &) {}
};
class Derived: public Base {};
void Func(Base)
{
}
//void Func(Derived)
//{
//
//}
//main
int main() {
Func(Derived());
}
The explicit keyword will make sure that the constructor will not be used as an implicit conversion operator - you have to call it explicitly when you want to use it.