Move constructor without implementation, yet it works - c++

Here is some code I wrote to illustrate my question:
struct Foo
{
Foo() {}
Foo( Foo && );
Foo( const Foo & ) = delete;
};
Foo GetFoo()
{
return Foo();
}
int main()
{
Foo f = GetFoo();
}
The deleted copy constructor prevents an implicit default move constructor, so I have to explicitely declare one. But I am neither using "= default" nor providing an implementation for it, yet the whole thing compiles and links properly. If I remove the declaration, it won't compile anymore.
I find it really surprising that the linker isn't complaining about the missing move constructor. Could you please help me understand why?

When initializing a variable in the form type identifier = Function(), the compiler affirms that a copy/move constructor is declared as usable, and then ignores it and tries to construct from the right side directly ("copy/move elision"). Then it has Function construct the variable directly into main, to skip a move/copy (this is "return value optimization"). These sort of work together and bypass any and all moves/copies, and Function ends up constructing f directly. Since the move constructor wasn't actually used, the linker didn't look for it, and thus failed to notice the missing definition.

Related

Can an unused function instantiate a variable template with side-effects according to C++14?

Here is my code:
#include <iostream>
class MyBaseClass
{
public:
static int StaticInt;
};
int MyBaseClass::StaticInt = 0;
template <int N> class MyClassT : public MyBaseClass
{
public:
MyClassT()
{
StaticInt = N;
};
};
template <int N> static MyClassT<N> AnchorObjT = {};
class UserClass
{
friend void fn()
{
std::cout << "in fn()" << std::endl; //this never runs
(void)AnchorObjT<123>;
};
};
int main()
{
std::cout << MyBaseClass::StaticInt << std::endl;
return 0;
}
The output is:
123
...indicating MyClassT() constructor was called despite that fn() was never called.
Tested on gcc and clang with -O0, -O3, -Os and even -Ofast
Question
Does this program have undefined behavior according to C++ standard?
In other words: if later versions of compilers manage to detect that fn() will never be called can they optimize away template instantiation together with running the constructor?
Can this code somehow be made deterministic i.e. force the constructor to run - without referencing function name fn or the template parameter value 123 outside of the UserClass?
UPDATE: A moderator truncated my question and suggested further truncation. Original verbose version can be viewed here.
Template instantiation is a function of the code, not a function of any kind of dynamic runtime conditions. As a simplistic example:
template <typename T> void bar();
void foo(bool b) {
if (b) {
bar<int>();
} else {
bar<double>();
}
}
Both bar<int> and bar<double> are instantiated here, even if foo is never invoked or even if foo is only ever invoked with true.
For variable template, specifically, the rule is [temp.inst]/6:
Unless a variable template specialization has been explicitly instantiated or explicitly specialized, the variable template specialization is implicitly instantiated when it is referenced in a context that requires a variable definition to exist or if the existence of the definition affects the semantics of the program.
In your function:
friend void fn()
{
(void)AnchorObjT<123>;
};
AnchorObjT<123> is referenced in a context that requires a definition (regardless of whether fn() is ever called or even, in this case, it is even possible to call), hence it is instantiated.
But AnchorObjT<123> is a global variable, so its instantiation means we have an object that is constructed before main() - by the time we enter main(), AnchorObjT<123>'s constructor will have been run, setting StaticInt to 123. Note that we do not need to actually run fn() to invoke this constructor - fn()'s role here is just to instantiate the variable template, its constructor is invoked elsewhere.
Printing 123 is the correct, expected behavior.
Note that while the language requires the global object AnchorObjT<123> to exist, the linker may still the object because there is no reference to it. Assuming your real program does more with this object, if you need it to exist, you may need to do more to it to prevent the linker from removing it (e.g. gcc has the used attribute).
"If later versions of compilers manage to detect that fn() will never be called [and] they optimize away template instantiation" then those compilers would be broken.
C++ compilers are free to implement any optimization that has no observable effect. In the situation you have outlined there would be at least one observable effect: namely a static class member does not get constructed and initialized, so a C++ compiler cannot completely optimize that away. It won't happen.
A compiler can ignore everything else about the function call, and not actually compile the function call itself, but the compiler must do whatever it needs to do to make arrangements so that the static class member gets initialized as if that function call was made.
If the compiler can determine that nothing else in the program actually uses the static class member, and removing it completely has no observable effect, then the compiler can remove the static class member, and the function that initializes it (since nothing else references the function).
Note, that even taking an address of a function (or a class member) would result in an observable effect, so even if nothing actually calls the function, but something takes the address of the function, it can't just go away.
P.S. -- all of the above presumes no undefined behavior in the C++ code. With undefined behavior entering the picture, all the rules go out the window.
The short answer is it works.
The long answer is it works unless the linker discards your entire translation unit (.obj).
This can happen when you create a .lib and link it. The linker typically picks which .obj to link from the lib based on a dependency graph of "do I use symbols that obj exports".
So if you use this technique in a cpp file, that cpp files has no symbols that are used elsewhere in your exexutable (including indirectly via other obj in your lib that are in turn used by the executable), the linker may discard yoir obj file.
I have experienced this with clang. We where creating self registering factories, and some where being dropped. To fix it we created some macros that caused a trivial dependency to exist, preventing the obj file from being discarded.
This doesn't contradict the other answers, because the process of linking a lib is aboit deciding what is and what is not in your program.

Declare class object globally but without parameters

So here's my situation: I have a class foo residing in foo.cpp with header file foo.h included in my main.cpp. I need to be able to declare a foo object as a global variable in main.cpp so that it is available to all functions within main.cpp without having to pass a reference to it every time. The problem is, foo's constructor requires a variable which isn't retrieved from the user until halfway through the main function in main.cpp. I thought I could do this this way:
static foo myFoo;
As a global variable above the main function, then after the necessary data is retrieved from the user (let's call it "variable"), I could call:
myFoo = new foo(variable);
I'm getting an error however with this:
error: no matching function for call to ‘foo::foo()’
referencing the line with static foo myFoo;
So it's basically saying that I'm trying to declare an instance of foo with a constructor taking zero arguments, when there is none.
So my question is: Is there a way to declare a label myFoo out of foo as a global variable so that the program compiles, and then later it can actually be instantiated using the constructor with a variable passed?
I know I could just do something like this:
string temp = "";
static foo myFoo(temp);
above main() and then have some function defined where I could do
myFoo.setVar(variable);
when I needed to. To me this is very ugly and necessitates the inclusion of the function setVar which has no tangible purpose other than to circumvent this very issue. Thoughts?
One option you have is to make your static instance a pointer:
static foo *myFoo = NULL;
// Later...
myFoo = new foo(variable);
Or you may want to use a default constructor and make an Init method instead.
static foo myFoo;
// Later...
myFoo.Init( variable );
When you're exposing a variable, you don't define it as static. Remove the static keyword and use extern in the header's declaration.
static foo myFoo;
That line will create a new object of type foo during the static initialization if your program. It will call the default constructor (if you don't define one, the compiler will create one for you in certain situations - you haven't posted enough code to know if that is the case here). Note that if it is defined in a header file, you will need to extern it.
Attempting to set myFoo to a pointer using
myFoo = new foo(variable);
will not compile. new foo(...) returns a foo*, not a foo. If you want it to be a pointer, you need to declare your static variable as
static foo* myFoo;
If you want it to be an object and want to set it to something other than the default, you can implement a copy-assignment operator and do something like this
foo newFoo(variable);
myFoo = newFoo;
Or provide an initialization function to change the construction values after the fact (prefer the copy-assignment in most cases as it will be less prone to errors).
I believe you might not be defining the default constructor. Once you define a constructor, the default constructor is not automatically defined. This works for me:
myclass.hpp:
#ifndef _MYCLASS_
#define _MYCLASS_
class myClass
{
public:
int I;
myClass(int i);
myClass();
};
#endif
myclass.cpp:
#include "myclass.hpp"
myClass::myClass(int i) : I(i) {};
myClass::myClass() : I(0) {};
main.cpp:
#include "myclass.hpp"
myClass myGlobalClassObject;
int main()
{
myClass myLocalClassObject(1);
myGlobalClassObject.I = 2;
return 0;
}
You are indicating that you foo object cannot be properly instantiated until halfway down the main function. This sounds like you will have an object in an inconsistent state for the first half of your main function. Very dangerous.
Anyway, there is a couple of ways to get to it:
1) If you want to create a static foo object you can use a default value for your constructor:
class foo {
public:
foo( type variable = default ) {
...
}
...
You can now declare your foo object as a global in main
foo myFoo;
and myFoo's variable will be initialised with “default”
or, without a default:
class foo {
public:
foo( type variable ) {
...
}
...
Declare your foo object as a global in main
foo myFoo(default);
Depending whether “default” makes sense in your application you can now use your myFoo object in main.cpp's functions. If “default” does not make sense you will have to add a test function before you use myFoo.
Of course you also need another member function to be able to set “variable” to your user input (something like set_variable(variable); )
2) Use a pointer. Declare a global foo * myFoo in main.cpp and test if the pointer is NULL before using it.
Now your constructor does not need a default value, it still needs the variable:
foo::foo(type variable) { ... }
You initialise your myFoo object by using: myFoo = new foo(user_input);
You can test the myFoo pointer to NULL as all uninitialised global variables are set to 0 by the startup code.
(As an aside: you do realise of course that globals are frowned upon and as such should be avoided)
Good luck

Anonymous object with one argument cannot be declared

There is this code:
class SomeClass
{
public:
SomeClass(){}
SomeClass(SomeClass& b){}
SomeClass(SomeClass&b, SomeClass& c){}
};
int main()
{
SomeClass a;
SomeClass(); // works all right
//SomeClass(a); error: redeclaration of ‘SomeClass a’
SomeClass(a, a); // works all right
return 0;
}
Anonymous object of SomeClass with 0 and 2 parameters can be declared, however it cannot be declared with only 1 argument. I assume that writing
SomeClass(a);
is the same as
SomeClass a;
How to create anonymous object with one argument?
You can construct a temporary object in a statement of its own with something like:
(SomeClass)a;
or
(SomeClass(a));
As you've observed, the parentheses are needed to resolve the ambiguity between a declaration and an expression statement.
You can create that anonymouse object as the following:
(SomeClass(a));
This resolves the ambiguity since it can't be a declaration of a.
(SomeClass a); // Error: this can't be a declaration because of the parentheses
// but what else should it be?
In that context, the braces are superfluous, which means
SomeClass(a); //declaration of a
is exactly equivalent to
SomeClass a; //declaration of a
which is again equivalent to these:
SomeClass((a))); //declaration of a
SomeClass(((a))); //declaration of a
SomeClass((((a)))); //declaration of a
SomeClass(((((a))))); //declaration of a
All of these declare a variable of name a and type SomeClass.
In general, you avoid the most vexing parse by writing code with the same effect as what you wanted to write, but that can't be parsed as a declaration.
Often, this is done by adding parentheses.
In this case (SomeClass(a)); will do, or (void) SomeClass(a);
Your assumption is correct.
You simply cannot create a temporary object with a single constructor argument in a context where the same statement could be a declaration. The grammar makes it ambiguous (or, it would be ambiguous if the behaviour you're seeing weren't defined to take precedence).
Why not give the object a name, instead?
SomeClass obj(a);
Or, if you have a reason to want the object to be destroyed immediately (sometimes this is useful; e.g. a boost::this_thread::interruption_point, though that takes no arguments), you can still create a temporary but de-ambiguate the statement:
(SomeClass(a)); // the parens prevent this from being a declarative statement
In some scenarios you may also be able to use C-style casts:
(SomeClass)a;
But, hopefully, your SomeClass constructor is actually marked explicit, and we prefer not to use C-style casts anyway.
This problem doesn't arise in other contexts, ones in which a temporary might make more sense anyway:
std::cout << SomeClass(a); // *can't* be a decl of a `SomeClass` called `a`

C++ - What is this doing if the constructor is private?

In the code below, why does the compiler not complain for mClass2?
class CMyClass{
private:
CMyClass(){}
};
void TestMethod(){
CMyClass mClass1; //Fails.
CMyClass mClass2(); //Works.
}
Because you've just declared a function mClass2 of zero arguments that returns a CMyClass. That's a valid option since there could be, say, a static CMyClass instance which that function has access to. Note that CMyClass still has a public copy constructor.
(To convince yourself, compile this module to assembler and observe that commenting out the line CMyClass mClass2(); produces the same output.)
Because it is declaring a function and not calling the constructor as you think.
This is called as the Most Vexing Parse in c++.
CMyClass mClass2();
declares a function mClass2() which takes no parameter and returns CMyClass
The second one is a function declaration.
People ought to move to the uniform syntax initialization in C++0x/C++11 using the {} brackets instead which removes this issue.
Class C{};
http://www2.research.att.com/~bs/C++0xFAQ.html#uniform-init

Using a class in a header file without access to its definition?

This is excerpt from google's c++ coding guidelines.
How can we use a class Foo in a header
file without access to its definition?
We can declare data members of type Foo* or Foo&.
We can declare (but not define) functions with arguments, and/or
return values, of type Foo. (One
exception is if an argument Foo or
const Foo& has a non-explicit,
one-argument constructor, in which
case we need the full definition to
support automatic type conversion.)
We can declare static data members of type Foo. This is because static
data members are defined outside the
class definition.
What I'm curious about is exception in the second bullet. Why is this so? Why is the full definition needed if we want to support automatic type conversion?
My guess is that compiler needs the full definition of the destination type because of the temporary object that is created in the implicit conversion. Am I guessing correctly? Is there more to it?
EDIT:
As I see it, the exception in the guideline is addressed to situation like this:
class A
{
public:
A( int );
};
class B
{
public:
B( A const &a );
};
int main()
{
B b(2);
}
Here we have only one user-defined implicit conversion (from int to A), and call to constructor that accepts A const &. Only thing that makes sense in this exception is to support direct conversion from e.g. int to A, and then to B via constructor that accepts A const &, allowing client code to use this conversion chain without need to explicitly include header file where A class is declared.
The C++ language doesn't differentiate between code in header files and other file. It does not even require that a header is a file. So purely technically the question is meaningless, but in practice you restrict what you do in header files so as not to run afoul of the One Definition Rule. Without restricting yourself, users would have to be careful to only include the header file in one translation unit. With proper restrictions, the header file can be freely included in multiple translation units.
An incomplete type is one where the size is not known, where sizeof cannot be used.
When the class definition is not known, class Foo is necessarily incomplete.
This means you cannot do things that requires the size to be known. And since incompleteness means that members are not known (they would necessarily be known if the size was known) you can't generally call any members. Exception: you can call the destructor, like in delete pFoo, and the compiler must accept that, but it's Undefined Behavior if class Foo has a non-trivial destructor.
The exception noted in the Google guidelines is, however, meaningless.
EDIT: I discovered that people on SO like it better when things are spelled out in detail, so, adding discussion of why the guideline is meaningless.
The guideline says you can "declare (but not define)" but that "one exception is if an argument Foo or const Foo& has a non-explicit, one-argument constructor".
The declaration does not have anything to do with constructors, which one can affirm by simply trying it out:
#include <iostream>
struct Foo;
Foo bar( Foo const& ); // Declaration of function bar, works fine.
struct Foo
{
int x_;
Foo( int x ): x_( x ) {} // Converting constructor.
};
int main()
{
std::cout << bar( 42 ).x_ << std::endl;
}
Foo bar( Foo const& foo ) { return foo; }
In conclusion, again, the Google guidelines' exception is meaningless.
Cheers & hth.,
Suppose that foo.h knows about Foo declaration only
//foo.h
class Foo;
void f(const Foo &); // It is possible to use the reference.
Full definition is in foo.cpp
// foo.cpp
class CanBeConvertedToFoo;
class Foo
{
Foo (const CanBeConvertedToFoo & x); // implicit constructor
}
class CanBeConvertedToFoo is implicit convertable to Foo;
But it is unknown in some.cpp.
// some.cpp
#include "foo.h"
void g(const CanBeConvertedToFoo & x) {
f(x); // Is it known about implicit conversion ?
}
I don't know whether the exception in the second point is true. Implicit conversions must be know only when a function is called, not when it is declared, so the following works even though C is incomplete while f is declared:
#include <iostream>
class C;
void f(C);
struct C { C(int i) { std::cout << "C(" << i << ")" << std::endl; } };
void f(C c) { std::cout << "f(C)" << std::endl; }
int main() { f(2); }