Local classes inside inline non-member function produces LNK2005 with MSVC2005 - c++

Apparently, MSVC2005 fails to inline local classes' member functions which leads to LNK2005.
I'm facing this LNK2005 error when compiling the following:
common.h content:
inline void wait_what()
{
struct wtf
{
void ffffuuu() {}
} local;
}
foo.cpp content:
#include "common.h"
void foo()
{
wait_what();
}
bar.cpp content:
#include "common.h"
void bar()
{
wait_what();
}
LNK2005.cpp content:
// forward declarations
void foo();
void bar();
int main()
{
foo();
bar();
return 0;
}
The error message is:
error LNK2005: "public void __thiscall `void__cdecl wait_what(void)'::`2'::wtf::ffffuuu(void)" (?ffffuuu#wtf?1??wait_what##YAXXZ#QAEXXZ) already defined in bar.obj
About local classes, ISO IEC 14882-2003 says:
9.8 Local class declarations
A class can be defined within a function definition; such a class is called a local class. The name of a local class is local to its enclosing scope. The local class is in the scope of the enclosing scope, and has the same access to names outside the function as does the enclosing function. Declarations in a local class can use only type names, static variables, extern variables and functions, and enumerators from the enclosing scope.
An enclosing function has no special access to members of the local class; it obeys the usual access rules (clause 11). Member functions of a local class shall be defined within their class definition, if they are defined at all.
Did I miss something?
To me, it looks like it is a compiler bug. GCC and MSVC2008 compile it just fine. However, I wonder whether they would really inline the call or just discard one of the two symbols during the link phase. As an interesting note, you can notice that there is even no call to this local class member function.
I wonder whether there is a workaround for MSVC2005. I tried to search MSDN for this typical problem without much success: I wasn't even capable of finding a list of known bugs for the compiler.
Attachment: LNK2005.zip

it was a bug in visual studio 2005, it was fixed in vs 2008

It looks like a bug to me. Maybe that's why it works in VS2008. (Incidentally, Microsoft, this is a good reason for breaking the IDE/compiler dependency in Visual Studio.)
As for a workaround, try explicitly adding inline, or not inlining wait_what.

Related

Does C++ accept inline virtual function while performing polymorphism?

//header.h
#include<iostream>
using namespace std;
struct Base {
virtual void vf();
};
struct Derived :Base {
virtual void vf();
};
inline void Base::vf() {
cout << "Base::vf()" << endl;
}
inline void Derived::vf() {
cout << "Derived::vf()" << endl;
}
//source.cpp
#include"header.h"
int main() {
Base *pb = new Derived;
pb->vf();
}
//source2.cpp
#include"header.h"
It compiles and works in MSVC and g++.
But if I remove both inline keywords, a duplicate definition error will be caught by the linker since I include function definition twice, which will break the ODR.
Since I call the virtual function with a base pointer, it should be decided at run-time, and the compiler will ignore my inlining request, causing the duplicate error.
Do I get something wrong?
As the code is currently written, the member functions are defined in header.h and marked inline. That's okay from the perspective of the language definition: inline means "it's okay to have multiple [identical] definitions of this function". From a maintenance perspective it can make things harder. In particular, when you do this, every time you change the implementation of any of those functions you have to recompile all of the source files that use that header. Putting the definitions of those functions into their own source file[s] means you only have to recompile the file[s] that changed.
If you don't want to mark your functions inline (and you don't want to define them inside the class definition, which makes them implicitly inline), then you have to put each function definition into exactly one source file. A useful first step is to define all of the non-inline member functions of a class in a single source file. So your source2.cpp might look like this (yes, that's member functions from two classes):
#include "header.h"
#include <iostream>
void Base::vf() {
std::cout << "Base::vf()\n";
}
void Derived::vf() {
std::cout << "Derived::vf()\n";
}
and you'd remove those definitions from header.h. So now header.h contains only the class definition; source2.cpp has the definitions of the member functions; and source.cpp has the main function.
The One Definition Rule is mandatory. It is required by C++. A given object or a function must be defined exactly once. Removing the inline keyword (in your case) violates this rule, making the resulting program ill-formed.
Runtime polymorphism and virtual function dispatch happens at run time. You can only get to the run time part if your program is well-formed. If it breaks the ODR it is not well-formed, so how runtime polymorphism and virtual function dispatch works becomes a moot point. If your program is ill-formed there won't be anything to run and no base pointer at all.
It is true that an ODR violation does not require a diagnostic, but the resulting code is still broken. Please write a thank-you note to your compiler for alerting you to the problem.

How to ensure a C++ function is declared before being defined (like the override keyword)?

In my shared library I declared a function in a header file, and defined it in a .cpp source file. When linking an application with the library, the linker complains that the function is undefined and I don't know whether it's because of a missing namespace, different parameters, or something else.
If I could mark the function definition as "implementing a previous declaration", I would catch this declaration/definition difference during compilation, instead of later when I link an app with the library.
Is there something similar to the "override" keyword for class methods that would prevent me from defining a function without an existing matching declaration ?
I could use -Wl,--no-undefined but some libraries were created with the expectation that --no-undefined will not be used.
Declare a function in a header file in a namespace, e.g.:
namespace N { void f(); }
Define the function in a .cc file using a qualified function name:
void N::f() { /*...*/ }
This way if no declaration of f in namespace N matches the definition, a compiler error is issued.
The other answer by Maxim Egorushkin can be simplified as follows for some compilers:
Declare the function as normal in the header file:
void f();
Define the function using a qualified name with the unnamed namespace:
void ::f() { /* ... */ }
Obviously you can also place it in a namespace.

Can a function be defined in global namespace if it is declared in an anonymous namespace?

In production code I found this in a .cpp file:
namespace
{
void foo(); // declared in anonymous namespace, defined below
}
void bar() // declared in corresponding .h file, defined here
{
::foo(); // call foo
}
void ::foo() // intended to refer to the anonymous foo above
{
}
We are using Visual Studio 2017. I stumbled over this because intellisense gave me a warning for foo that it could not find the function definition.
However, it compiles and links without errors and the code does what it is supposed to do.
I godbolted it and found that gcc and clang reject this code for the same reason that intellisense gave me a warning for.
So my question is: Which compiler is correct and why?
Furthermore, out of interest I added another declaration of foo to the global namespace, like so:
namespace
{
void foo();
}
void foo(); // another declaration
void bar()
{
::foo(); // which foo will be called?
}
void ::foo() // which foo will be defined?
{
}
Now, gcc gives me an error:
error: explicit qualification in declaration of 'void foo()'
Clang compiles it, but gives me a warning:
warning: extra qualification on member 'foo' [-Wextra-qualification]
And msvc compiles it just fine.
Again, which compiler - if any - is correct here?
Have a look at the cppreference page on unnamed namespaces:
This definition is treated as a definition of a namespace with unique
name and a using-directive in the current scope that nominates this
unnamed namespace.
So an "anonymous" namespace is not the global namespace, nor is it even unnamed. Rather, it has a compiler-provided unique name. So ::foo() is not the function in your anonymous namespace. MSVC is incorrect here.
And you can't define your anonymous namespace function outside its anonymous namespace.

When a method is defined inside class scope, project won't compile unless method is invoked somewhere else in the original cpp file

Here's the body of main.cpp
#include "Header.h"
int main()
{
auto f = Foo();
f.bar();
return 0;
}
Here's the body of Header.h
class Foo {
public:
void bar();
};
Here's the body of Source.cpp
#include <iostream>
class Foo {
public:
void bar() {
std::cout << "Foo.bar() called\n";
}
};
void t() {
auto f = Foo();
f.bar(); // If this line isn't here, the project won't compile
}
When I comment out f.bar(); in Source.cpp, I receive the following error upon compilation. It's telling me that f.bar() in main() is unresolved:
Error LNK2019 unresolved external symbol "public: void __thiscall
Foo::bar(void)" (?bar#Foo##QAEXXZ) referenced in function _main ...
I understand that it's common to define methods outside of class scope, and indeed the following version of Source.cpp compiles successfully--
#include <iostream>
#include "Header.h"
void Foo::bar() {
std::cout << "Foo.bar() called\n";
}
Nonetheless, I don't understand what's wrong with the original version. It feels like something mysterious and magical is going on that I don't fully understand.
This is an ODR violation either way, because the class Foo as defined in the header, and the class Foo as defined in the cpp file are not token by token identical.
out of line definition of bar should look like
#include <iostream>
#include "Header.h"
void Foo::bar() {
std::cout << "Foo.bar() called\n";
}
Note that ODR violations are 'no diagnostics required'
(this is why one of the examples compiles, the compiler can't always detect ODR violations)
The best way to not accidentally create errors like this is to always include the header-file in the file/files where you implement the methods.
When we are talking about good practices, don't forget the include-guard in the header-file.
If a method is short enough to be inline defined, (style may vary, but for me that means a short oneliner), then that inline definition need to be present in the header-file, so that the compiler sees an identical type every time it encounters it.
Your original program violates the One Definition Rule (ODR), defined in C++14, 3.2. The relevant paragraph is number 6:
There can be more than one definition of a class type [...] in a program
provided that each definition appears in a different translation unit,
and provided the definitions satisfy the following requirements. Given such
an entity name D defined in more than one translation unit, then
each definition of D shall consist of the same sequence of tokens; and
[...]
You have two translation units: main.cpp with all its header files (including Header.h), and Source.cpp with all its header files (which do not include Header.h). Both translation units contain a definition of the class ::Foo: main.cpp contains the one from Header.h, and Source.cpp has its own.
However, the two do not consist of the same sequence of tokens. The one in Source.cpp contains an inline function definition.
The reason for having one definition of a class in a header and only getting it by including this header is two-fold:
You save the effort of duplicating it, and more importantly, finding every duplicate if you have to change it.
Barring preprocessor shenanigans, with there being only one textual form of the definition, you cannot run afoul of the ODR.
Note that ODR violations are "no diagnostic required" - in your case you get an error, but as you saw, the error disappears if you call the function in Source.cpp. That doesn't mean your program became correct; it just means that the compiler was no longer capable of discovering the error; nonetheless, very strange behavior could occur. Your program has undefined behavior.
Take a look at the C++ standard 9.3.2 (n4296):
" ... A member function may be defined (8.4) in its class definition, in which case it is an inline member function
(7.1.2), or it may be defined outside of its class definition if it has already been declared but not defined
in its class definition. A member function definition that appears outside of the class definition shall appear
in a namespace scope enclosing the class definition. Except for member function definitions that appear
outside of a class definition, and except for explicit specializations of member functions of class templates
and member function templates (14.7) appearing outside of the class definition, a member function shall not
be redeclared ..."
& 9.3.3 :
" ...An inline member function (whether static or non-static) may also be defined outside of its class definition
provided either its declaration in the class definition or its definition outside of the class definition declares
the function as inline.[ Note: Member functions of a class in namespace scope have the linkage of that
class. Member functions of a local class (9.8) have no linkage. See 3.5. —end note ] ..."
Since bar() is defined inside Foo { }; it is implicitly inline.
I believe taking the above clauses into consideration together implies that Foo::bar has local linkage in Source.cpp & is not visible to anyone else. What I find confusing is that calling f.bar() changes the linkage allowing your other example to compile.
Compiler take the cpp files one by one, there's no way the compiler will remember what else he compiled in another file
main.cpp - include header. Header contains a class declaration. main.obj expects that foo() will be implemented as a separate symbol available at linking time. Done, write the object file and forget
Source.cpp redeclare the class without including the header. As such, the compiler cannot complain of the double declaration. As in the Source.cpp declaration the foo method is implemented inline, the compiler (not knowing anything about what main expects) does not generate a linkage symbol for the method, Done, write the object and forget
linker loads both objects, see that the 'main.obj' needs a linkage symbol for the foo method, searches everywhere and cannot find one - because the Source.obj does not contain one - the compiler was instructed the method will be inline.
Makes sense?

Is it not necessary to define a class member function?

The following code compiles and runs perfectly,
#include <iostream>
class sam {
public:
void func1();
int func2();
};
int main() {
sam s;
}
Should it not produce a error for the lack of class member definition?
If you don't call the member functions, they don't have to be defined. Even if you call them, the compiler won't complain since they could be defined in some other compilation unit. Only the linker will complain. Not defining functions is accepted and common to force an error for undesired behavior (e.g. for preventing copying).
Yes it is perfectly valid to not define a class member function if it is not used. That is also true for non-member functions. A definition is required for virtual functions, though. But pure virtuals can omit definitions if they aren't used.
"Used", btw, does not include refering to the function within sizeof. In other words, this is still valid:
sizeof (s.func2()); // still not used!
You can define it elsewhere (like another file)
void Sam::func1()
{
// do stuff here
}
From MSDN Linker Error LNK2019
You did define declared it. You just didn't add implementation provided a function prototype. The linker may display a warning if you do not have a function definition (for instance, Borland C++ Builder 5 does not).