Why const object must have a user-provided constructor? [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
declaring a const instance of a class
Why does C++ require a user-provided default constructor to default-construct a const object?
My program like this:
class c
{
};
int main()
{
const c a;
return 0;
}
when I compile it using g++, it prompt:
main.cpp:10:7: note: ‘const class c’ has no user-provided default constructor
Why, this is just an empty class and do not do anything, why I have to provide a user-provided constructor.

Because the language rules say so.
The constant must have its value set in the definition, as it cannot be assigned a value later. If you don't explicitly provide a value, the type must have a default constructor.

You don't have to. It's just a note, not even a warning. The rationale is that the class can't do anything useful, which is rarely intended. GCC is just checking to see if you overlooked something.

Related

Is object construction expression well-formed even if that construction cannot be compiled? [duplicate]

This question already has an answer here:
std::unordered_map<T,std::unique_ptr<U>> copyable? GCC bug?
(1 answer)
Closed 2 years ago.
Suppose we have a non-copyable type X:
struct X
{
X(X&&) = default;
X(const X&) = delete;
}
Then, naturally, we cannot copy a container having X as value type:
std::set<X> v;
std::set<X> v2{v} // error
My question is, whether the expression that involves such a copy is well-formed? For instance, the following expression compiles:
sizeof( std::set<X>{v} )
I am asking since I run into the following problem:
std::cout << std::is_copy_constructible_v< X >;
std::cout << std::is_copy_constructible_v< std::set<X> >;
Which prints out 01. It's a bit counter-intuitive that std::set<X> is "reported" being copy-constructible when in fact it is not (by means of that its copy constructor cannot be called).
That comes from a problem you have, when your container shall support incomplete types. You cannot do both
Support incomplete types
SFINAE out the special member functions based on copy-ability of the value type
If you support incomplete types, you cannot check in the declaration of the copy constructor if that type is copyable (since it could be incomplete at that point). So, you can always instantiate the copy constructor. But if you do, that will fail in evaluated contextes.
There is a good article on this: https://quuxplusone.github.io/blog/2020/02/05/vector-is-copyable-except-when-its-not/

What is an example of implicit declaration in terms of static type binding? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am currently studying the programming topic of type binding. I understand that type binding is the association between a variable and a type and that there are 2 types of type binding. Static type binding (type binding that occurs during compile time) and Dynamic type binding (type binding that occurs during run time). In addition, static type binding is achieved by 2 methods, the first being explicit declaration (a programming statement used for declaring the types of variables) and implicit declaration. An example of explicit declaration would be as simple as
int x; // Variable bounded to int type during compile time
However, implicit declaration is much harder for me to grasp. As a result, can anyone post a simple example of code that uses implicit declaration? Thanks in advance everyone.
I think C++ don't support implicit declaration so I will assume that you are talking about implicit conversion.
An easy way to ilustrate the implicit conversion might be the next:
int x = 1;
double y = x; // 1 will be converted into 1.0 in runtime
string s = '1.2';
double z = (double)s;
double z2 = (double)'aa'; //throws an exception
If we were talking about JavaScript, a good example could be:
var x; //x has no type yet
x = 1; //type of x will be determinated on runtime
I hope It is usefull and help you to understand.
Older C had some degree of implicit declaration.
If you used a function without an explicit declaration, the compiler was required to act as if you'd declared it a the number and type of parameters based on the number and type of arguments you passed (and if the function definition didn't agree, you got undefined behavior.
Likewise, you could define a function without explicitly declaring its return type (which then implicitly defaulted to int).
int f() {
g(1); //implicitly declared to take an int parameter and return an int
}
g() { return 1; } // return type implicitly declared as int
Most of this is now obsolete though. For example, the implicit return type existed in C89/90, but was removed in C99.
C++ has some implicit declarations as well, but they're rather different. For one example, if you create a class in C++, the compiler will usually1 implicitly declare (for a couple of examples) a default constructor and a copy constructor if you don't explicitly declare a constructor.
struct A {
int b;
};
This has an implicitly declared default constructor, copy constructor, move constructor, copy assignment operator, and move assignment operator. Most of these (all but the default ctor) take parameters (which are variables) with implicitly bound types.
Note that in this case the implicit declaration is of functions, not variables, so it may be open to question whether this qualifies as exactly what you're trying to discuss or not (but at the very least it's quite similar). As ntoed above, most of the functions take parameters, which are variables that have types that are implicitly defined.
The implicit declarations sometimes don't happen, such as if the class contains a non-static const member variable, or a variable of reference type.

Clang Compile error with default initialization [duplicate]

This question already has answers here:
Do I really need to implement user-provided constructor for const objects?
(4 answers)
Closed 8 years ago.
Consider following example:
#include <iostream>
#include <type_traits>
struct A
{
//A() = default; // does neither compile with, nor without this line
//A(){}; // does compile with this line
int someVal{ 123 };
void foobar( int )
{
};
};
int main()
{
const A a;
std::cout << "isPOD = " << std::is_pod<A>::value << std::endl;
std::cout << "a.someVal = " <<a.someVal << std::endl;
}
See Live example
This does compile with g++ but does not compile with clang++, tried with following command: clang++ -std=c++11 -O0 main.cpp && ./a.out
Compile error from clang:
main.cpp:19:13: error: default initialization of an object of const type 'const A' requires a user-provided default constructor
I learned from This Stack Overflow Question, that non-POD classes get default constructor. This is even not necessary here because the variable has c++11-style default initialization
Why does this not for clang?
Why does A() = default; not work, too?
This is addressed in CWG issue #253 which discusses the need for a user provided constructor for empty objects or objects whose subobjects are fully initialized (which is the case in your example).
Quoting part of the linked issue
Notes from the August, 2011 meeting:
If the implicit default constructor initializes all subobjects, no initializer should be required.
Technically it is an active issue but given that note it seems likely that it'll be resolved the way gcc chose to implement it.
Clang, on the other hand, has chosen to wait until the issue is resolved before implementing a solution.
In Clang, we're waiting for the issue to actually be resolved before we take a direction on it.
So, as it currently stands, clang is correct.
You quoted the answer yourself. In the SO answer that you linked, there is the following quote from the standard (section 6.8.6precisely):
If a program calls for the default initialization of an object of a
const-qualified type T, T shall be a class type with a user-provided
default constructor.
emphasis mine. The line
A() = default;
obviously does not provide a constructor, it does the opposite by telling the compiler that you don't want to provide one, thus your code doesn't compile. However, once you provide the constructor by uncommenting
A(){};
it works fine. So, to summarize, the error that clang shows is per standard, and the behaviour of gcc is probably a bug.

How are copy constructors used and why are they important? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
What are copy constructors?
Why do we use them? Is it necessary to call a destructor if we do?
What is a copy constructor?
Quoting the C++11 standard, §12.8/2:
“A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&,
volatile X& or const volatile X&, and either there are no other parameters or else all other parameters
have default arguments”
So there are 4 different forms. Of these the X const& form is the one most often used. This is also the form of the implicit copy constructor that is generated (if possible) if no copy constructor is declared for the class.
A copy constructor is used for copying an object to a new instance of the class. A default copy constructor performs a member-wise copy, which is different from and more safe than just copying the bits. In particular a copy constructor or move constructor is logically used for a copy initialization, an initialization using the = sign like
Some_type x = expression;
In some circumstances the compiler is allowed to assume that copying is all that a copy constructor does, regardless of what it actually does. Logically needless copy constructions can then be removed, or as the standard calls it, elided. For example, if the expression above is the number 42, then instead of using that argument to construct a temporary and copying or moving that to x, the argument may be used to initialize x directly.
However, even when that is done, so that the copy constructor is not used, if the copy constructor would have been used except for the optimization then a copy constructor must exist and be accessible.
C++11 §12.2/1:
“Even when the creation of the temporary object is unevaluated (Clause 5)
or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object had
been created and later destroyed.”
Is it necessary to call a destructor?
Re “Is it necessary to call a destructor if we [use a copy constructor]? ”.
Generally no.
Destructors in C++ are called automatically when an object goes out of scope or when it's indirectly or directly destroyed via delete. The only exception is for placement new, which is a low level feature that has nothing in particular to do with copy constructors. Although placement new can involve copy construction.
A difference between C++03 and C++11 copy constructors.
To understand the difference between C++03 and C++11 regarding copy constructors you must be aware of three facts:
If a copy constructor isn’t declared, then it’s generated if possible. Hence by default every class has a copy constructor. It’s there.
Access is independent of overload resolution.
Overload resolution chooses between all member functions, regardless of whether they’re accessible or not. Then access is checked. At that point you may get an error message about calling an inaccessible function, despite an expectation that overload resolution ideally should choose only from the accessible functions…
An ordinary function (or just function) is a better match than a an instantiation of a function template with the same signature.
Here is an example of overloading resolution choosing a private member function, in spite of a public function that could be called:
File [access_versus_overload_resolution.cpp]
class C
{
public:
void foo( double );
void foo( int );
void bar( double );
private:
void bar( int );
};
int main()
{
C().foo( 42 ); // OK.
C().bar( 42 ); //! Uh oh, inaccessible.
}
And here is an example of an ordinary function trumping a template instantiation:
File [function_versus_template.cpp]
using One = char[1];
using Two = char[2];
auto foo( char const* ) -> One&;
auto foo( char const (&)[10] ) -> Two&;
auto bar( char const* ) -> One&;
template< int n >
auto bar( char const (&)[n] ) -> Two&;
#include <iostream>
auto main() -> int
{
using namespace std;
//cout << sizeof( foo( "Blah blah" ) ) << endl; //! Ambiguous
cout << sizeof( bar( "Blah blah" ) ) << endl; // "1"
}
With these facts at hand:
An inaccessible copy constructor will be chosen even if there is an accessible member function template that is just as good a match.
(As a logical consequence of the general overload resolution rules.)
In C++11, a member function template instantiation will therefore be chosen only if it is a better match than the copy constructor, if any.
But in C++03 there was a special rule that ensured that with a conforming compiler a function member template would never be used to copy an object.
Here’s the C++03 wording, §12.8/3 in that standard, where I’ve added suitable emphasis:
“A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv-
qualified) X and either there are no other parameters or else all other parameters have default arguments. A
member function template is never instantiated to perform the copy of a class object to an object of its class
type.
while in C++11 the wording is subtly changed, in that standard’s §12.8/6, where again I’ve added suitable emphasis:
“A declaration of a constructor for a class Xis ill-formed if its first parameter is of type (optionally cv-qualified)
X and either there are no other parameters or else all other parameters have default arguments. A member
function template is never instantiated to produce such a constructor signature.”
I.e. no special injunction against function templates being used to copy objects in C++11.
Unfortunately for history buffs, the most readily available C++03 compiler for Windows, namely MinGW g++ of some old version such as 3.2, does not enforce the C++03 rule.
File [template_versus_cc.cpp]
class S
{
private:
S( S const& ); // No such.
public:
S() {}
template< class T >
S( T& ) {}
};
int main()
{
S sm;
S const sc;
S s1( sm ); // OK in C++11, template is better match.
S s2( sc ); //! Line 19. Copy constructor is selected, inaccessible.
}
Compiling with old g++:
[H:\dev\test\copy_construction]
> \bin\MinGW_3_1\bin\g++ --version | find "++"
g++ (GCC) 3.2.3 (mingw special 20030504-1)
[H:\dev\test\copy_construction]
> \bin\MinGW_3_1\bin\g++ -std=c++98 -pedantic template_versus_cc.cpp
template_versus_cc.cpp: In function `int main()':
template_versus_cc.cpp:4: `S::S(const S&)' is private
template_versus_cc.cpp:19: within this context
[H:\dev\test\copy_construction]
> _
By the C++03/C++98 rules the compiler should have flagged both copy initializations, at lines 18 and 19, but only flagged the latter, behaving as a C++11 compiler in this respect.
This is also what the more modern g++ 4.8.2 does, as well as Visual C++ 12.0. But a conforming C++03-compiler must diagnose both initializations.
Scott Meyers has written about this, citing two of the SO C++ Lounge dwellers as sources. Unfortunately the article yields the impressions that (1) it’s all about universal reference template arguments in C++11, and (2) there’s is no bug in g++. The former is wrong, as shown above, while the latter is literally correct. There was a bug, but as the standard has evolved, with C++11 the g++ behavior is now conforming…
Copy constructors are important for quite the same reasons as a regular constructor would be, and that is to properly initialize the constructed object. Construction is not always trivial, and it doesn't matter where do you take the data from and in what form - other object of the same class or a set of simpler arguments.
Therefore copy constructor is there to solve problems like initializing const fields, but also when you use pointers, to decide on ownership of the pointed resource. You may want to share, or duplicate the data.

c++ operator must be non static member function [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What does “operator = must be a non-static member” mean? (C++)
I'm trying to write an operator= method as a non member, with 2 arguments like this:
template<class T>
T operator=(T & t, const myclass<T>& m)
{
t = m.val;
return t;
}
But I get the error that operator= must be a nonstatic member. Is there a compiler flag or some way to trick the compiler to let me run this?
Thanks
No there is not, this is mandated by the standard, paragraph 13.5.3.1:
An assignment operator shall be
implemented by a non-static member
function with exactly one parameter.
There isn't, assignment operators need to be declared as members (The rationale is, iirc, to keep you from overriding assignment for primitive or library types).