To fix a problem caused by the static (de-)initialization order fiasco I tried to use the Nifty Counter idiom aka Schwartz Counter. I noticed, however, that it does not work if the header file containing the static initializer is included inside Visual Studio's precompiled header. In such a case I see in the debugger, that the constructor of the static initializer is called after the constructor of the other static object.
If I declare an additional static initializer right after #include "stdafx.h" or edit the precompiled header to not contain the declaration it works as expected.
Any ideas what might cause this?
EDIT
I was finally able to reproduce this problem in a new dummy project:
Foo.cpp
#include "stdafx.h"
#include "Foo.h"
#include <cassert>
#include <iostream>
#ifdef NIFTY
static int SchwartzCounter; // zero initialized at load time
static typename std::aligned_storage<sizeof(Foo), alignof (Foo)>::type foo_buf;
Foo& foo = reinterpret_cast<Foo&>(foo_buf);
#else
Foo foo;
#endif
Foo::Foo()
{
std::cout << __func__ << std::endl;
}
Foo::~Foo()
{
std::cout << __func__ << std::endl;
}
void Foo::doSomething()
{
std::cout << __func__ << std::endl;
assert(x == 42);
}
#ifdef NIFTY
FooInitializer::FooInitializer()
{
std::cout << __func__ << std::endl;
if (SchwartzCounter++ == 0)
{
new (&foo) Foo();
}
}
FooInitializer::~FooInitializer()
{
std::cout << __func__ << std::endl;
if (--SchwartzCounter == 0)
{
(&foo)->~Foo();
}
}
#endif
Foo.h
#pragma once
class Foo
{
public:
Foo();
~Foo();
void doSomething();
private:
int x = 42;
};
#ifdef NIFTY
extern Foo& foo;
static struct FooInitializer {
FooInitializer();
~FooInitializer();
} fooInitializer;
#else
extern Foo foo;
#endif
Bar.cpp
#include "stdafx.h"
#include "Foo.h"
#include "Bar.h"
#include <cassert>
#include <iostream>
#ifdef NIFTY
static int SchwartzCounter; // zero initialized at load time
static typename std::aligned_storage<sizeof(Bar), alignof (Bar)>::type bar_buf;
Bar& bar = reinterpret_cast<Bar&>(bar_buf);
#else
Bar bar;
#endif
Bar::Bar()
{
std::cout << __func__ << std::endl;
foo.doSomething();
}
Bar::~Bar()
{
std::cout << __func__ << std::endl;
}
void Bar::doSomething()
{
std::cout << __func__ << std::endl;
assert(x == 42);
}
#ifdef NIFTY
BarInitializer::BarInitializer()
{
std::cout << __func__ << std::endl;
if (SchwartzCounter++ == 0)
{
new (&bar) Bar();
}
}
BarInitializer::~BarInitializer()
{
std::cout << __func__ << std::endl;
if (--SchwartzCounter == 0)
{
(&bar)->~Bar();
}
}
#endif
Bar.h
#pragma once
class Bar
{
public:
Bar();
~Bar();
void doSomething();
private:
int x = 42;
};
#ifdef NIFTY
extern Bar& bar;
static struct BarInitializer {
BarInitializer();
~BarInitializer();
} barInitializer;
#else
extern Bar bar;
#endif
stdafx.h
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// If the following define is commented out, the nifty counter idiom is not used
#define NIFTY
// If the following include is commented out while the nifty counter idiom is used, the initialization order is correct
#include "Foo.h"
Related
i have 2 .h files:
first.h
namespace first
{
void foo() { std::cout << 1 << ","; }
void bar() { std::cout << 7; }
}
second.h
namespace second
{
void foo() { std::cout << 3 << ","; }
void bar() { std::cout << 9; }
}
and the main.cpp
#include <iostream>
#include "first.h"
#include "second.h"
......................
void main() {
foo();
bar();
}
The goal is that the main prints 3,7 using these h files above.
Does someone have an idea how I could do it? Thanks
You can call the functions using the namespace:
second::foo();
first::bar();
But if you want to use the same functions over and over you can bring them into your scope via
using second::foo;
using first::bar;
foo();
bar();
I have the following three source files:
main.cc:
#include "constants.h"
#include <cstdlib>
#include <iostream>
template <std::size_t n> class Foo {
public:
static const double bar;
Foo();
};
template <std::size_t n> const double Foo<n>::bar = 4*pi;
template <std::size_t n> Foo<n>::Foo() { std::cout << "ctor: " << bar << std::endl; }
const Foo<42> baz;
int main(void)
{
std::cout << "main(): " << Foo<42>::bar << std::endl;
std::cout << "main(): " << baz.bar << std::endl;
return 0;
}
constants.cc:
#include "constants.h"
const double pi = 3.1415;
constants.h:
#ifndef CONSTANTS_H
#define CONSTANTS_H
extern const double pi;
#endif
and when I compile and link everything and run the executable I get:
ctor: 0
main(): 12.566
main(): 12.566
What gives? How comes the constructor of Foo<42> can't see the correct value of pi? This seems to only happen if Foo is a template, and only if pi is defined in a different file.
For what it's worth I'm using g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0. All of --std={c++,gnu++}{98,03,11,14,17} give the same results.
TIA for your answers.
Could you please explain to me why this code using conditional compilation does not compile?
// Example program
#include <iostream>
#include <string>
class Foo{
public:
#ifdef NUMBER
int number(){
return 0;
}
#endif
int number1(){
return 1;
}
};
int main()
{
#ifndef NUMBER
#define NUMBER
Foo foo;
std::cout << foo.number();
#endif
std::cout << foo.number1();
return 0;
}
It shows compilation error:
In function 'int main()':
22:26: error: 'class Foo' has no member named 'number'
As commented, the preprocessor only goes forward.
Here are the lines of your code where NUMBER is not defined:
// Example program
#include <iostream>
#include <string>
class Foo{
public:
#ifdef NUMBER
int number(){
return 0;
}
#endif
int number1(){
return 1;
}
};
int main()
{
#ifndef NUMBER
Here are the lines of your code where NUMBER is defined:
#define NUMBER
Foo foo;
std::cout << foo.number();
#endif
std::cout << foo.number1();
return 0;
}
NUMBER is only defined once you #define NUMBER.
In your code, there is no Foo::number().
I want to test defining a const in a header and use it in functions, then call it. However I get the error, I added include guards which doesn't help. Error is: LNK1169: One or more defined multiply symbols found. How can i do it in a nother way? Is declaring const in .h and defining this const in .cpp and then including this .cpp in all other .cpps the only solution?
Header
#ifndef STORY
#define STORY
const int x = 4;
#endif
.cpp
#include <iostream>
#include "8-04.h"
void func1()
{
int w = x;
std::cout << "func1 " << w << std::endl;
}
.cpp
#include <iostream>
#include "8-04.h"
void func2()
{
int z = x;
std::cout << "func2 " << z << std::endl;
}
main
#include <iostream>
#include "8-04.h"
#include "8-04first.cpp"
#include "8-04second.cpp"
using namespace std;
int main()
{
func1();
func2();
}
The problem is that each .cpp includes the .h. This means that each .o contains a const int x. When the linker links these together, you get multiple definitions.
The solution is to modify the .h
#ifndef STORY
#define STORY
extern const int x; //Do not initialise
#endif
and in a single .cpp:
const int x=4
Edit:
I didnt even see the #include <file.cpp> business. Don't do that. Its horrible.
This should be like :
header.h:
#ifndef STORY
#define STORY
const int x = 4;
void func1();
void func2();
#endif
fun1.cpp
#include <iostream>
#include "header.h"
void func1()
{
int w = x;
std::cout << "func1 " << w << std::endl;
}
fun2.cpp
#include <iostream>
#include "header.h"
void func2()
{
int z = x;
std::cout << "func2 " << z << std::endl;
}
main.cpp
#include <iostream>
#include "header.h"
using namespace std;
int main()
{
func1();
func2();
}
You can not include ".cpp"
It can be done such as :
header.h:
#ifndef STORY
#define STORY
const int x = 4;
void func1();
void func2();
#endif
fun1.cpp
#include <iostream>
#include "header.h"
using namespace std;
void func1()
{
int w = x;
cout << "func1 value of w = " << w << "\n";
}
fun2.cpp
#include <iostream>
#include "header.h"
using namespace std;
void func2()
{
int z = x;
cout << "func2 value of z = " << z << "\n";
}
main.cpp
#include <iostream>
#include "header.h"
int main()
{
func1();
func2();
}
".cpp" file cannot be included in main source file.
As you can see, the title is a little nonsense, it's because I really don't know how to call that, but know that I tried hard to find a better title.
I hope you understand what I'm trying to say seeing the rest of the question.
Let's suppose that I have 3 classes, "A", "B", and "C".
The class "A" includes "B" and "C".
The class "B" includes "A"
The class "C" includes "A"
Let's go the code...
#include <iostream>
#include <b.hpp>
#include <c.hpp>
class A
{
public:
A()
{
std::cout << "Hello from A" << std::endl;
A a;
B b;
}
};
#include <iostream>
#include <a.hpp>
class B
{
public:
B()
{
std::cout << "Hello from B" << std::endl;
}
};
#include <iostream>
#include <a.hpp>
class C
{
public:
C()
{
std::cout << "Hello from C" << std::endl;
}
};
This way, everything works fine, the output:
Hello from A
Hello from B
Hello from C
BUT, if I do that:
#include <iostream>
#include <a.hpp>
#include <vector>
class B
{
public:
B()
{
std::cout << "Hello from B" << std::endl;
}
private:
std::vector<A> garage;
};
I got a cascade of errors, including this one (actually, the main one, because of that one, there are others):
error: 'A' was not declared in this scope
std::vector garage;
This is exactly what I want, do you have an idea what I can do? Thank you.
#edit - As answer to #Kerrek SB
I tried to create separated files to each one, header and sources. (.hpp and .cpp) and the error persist.
A.hpp
#ifndef A_HPP
#define A_HPP
#include <iostream>
#include <B.hpp>
#include <C.hpp>
class A
{
public:
A();
};
#endif
A.cpp
#include <A.hpp>
A::A()
{
std::cout << "Hello from A" << std::endl;
B b;
C c;
}
B.hpp
#ifndef B_HPP
#define B_HPP
#include <iostream>
#include <A.hpp>
#include <vector>
class B
{
public:
B();
private:
std::vector<A> garage;
};
#endif
B.cpp
#include <B.hpp>
B::B()
{
std::cout << "Hello from B" << std::endl;
}
C.hpp
#ifndef C_HPP
#define C_HPP
#include <iostream>
#include <A.hpp>
class C
{
public:
C();
};
#endif
C.cpp
#include <C.hpp>
C::C()
{
std::cout << "Hello from C" << std::endl;
}
main.cpp
#include <iostream>
#include <A.hpp>
int main(int argc, char ** argv)
{
A a;
return 0;
}
gcc
g++ -O2 -std=c++11 -I"." -o exchange A.cpp B.cpp C.cpp main.cpp
output
In file included from ./A.hpp:5:0,
from ./C.hpp:5,
from C.cpp:1:
./B.hpp:13:17: error: 'A' was not declared in this scope
std::vector<A> garage;
Separate the class definitions from the class member definitions:
#include <iostream>
#include <vector>
class A { public: A(); };
class B { public: B(); private: std::vector<A> garage; };
class C { public: C(); };
A::A()
{
std::cout << "Hello from A" << std::endl;
// A a; // no, because that's idiotic
B b;
}
B::B()
{
std::cout << "Hello from B" << std::endl;
}
C::C()
{
std::cout << "Hello from C" << std::endl;
}
In a larger project, you would probably have separate header and source files for each of those.