How to add a struct to a vector from another class? - c++

I am student, and I am trying to build a project. My program is throwing an error while accessing the vector. The size of the vector is 1, but when I call RenderQueue.front it throws an error:
front() called on empty vector.
My code is below:
global.h
struct RenderStruct {
std::function<void()> testfunction1;
std::function<void()> testfunction2;
};
static std::vector<RenderStruct> RenderQueue;
Test.h
class test
{
public:
static void add_to_queue();
};
Test.cpp
void test::add_to_queue()
{
std::function<void()> testfunction1 = [&]()
{
std::cout << "First Function Working" << std::endl;
};
std::function<void()> testfunction2 = [&]()
{
std::cout << "Second Function Working" << std::endl;
};
RenderQueue.push_back({testfunction1, testfunction2});
};
Main.cpp
int main()
{
test::add_to_queue();
auto front = RenderQueue.front();
front.testfunction();
front.testfunction2();
};

static linkage variables are not shared between compilation units (cpp files).
Make your variable non static, mark it as extern, then export it from one cpp file (by declaring it without extern there).

Related

Uninitialized global variable in the map inside class metod

I have the following problem, I have a class that I want to be constructed from two different kinds of complex objects. There is a map inside a class method, that constructs from extern variables that I defined in the outer of the class. If I want to declare a class object inside the main function everything goes fine. But if I declare it outside the main, constructor of the class is called before the initialization of the extern objects from which I constructed the inner map in the class method. The error repeats itself on Clang and MSVC. If I use simple objects to construct the map (like int or double), everything works fine in both ways.
main.cpp
#include "TestClass.h"
TestClass test1 = TestClass(g_Spec1); // 1
int main()
{
TestClass test2 = TestClass(g_Spec1); // 2
}
If you comment 1 everything works fine, however, as is, 2 didn't see extern variables.
TestClass.h
#pragma once
#include <iostream>
#include <map>
#include "Token.h"
extern const Spec_t g_Spec1;
extern const Spec_t g_Spec2;
extern const Spec_t g_Spec3;
extern const Name_t g_Name1;
extern const Name_t g_Name2;
extern const Name_t g_Name3;
class TestClass {
private:
Name_t name;
Spec_t spec;
static const Name_t& foo(const Spec_t& j);
public:
TestClass() = default;
TestClass(const Spec_t& j);
virtual ~TestClass() = default;
};
TestClass.cpp
#include "TestClass.h"
const Spec_t g_Spec1{ {Token::Type1, 2} };
const Spec_t g_Spec2{ {Token::Type1, 3} };
const Spec_t g_Spec3{ {Token::Type1, 4} };
const Name_t g_Name1{ "Name1" };
const Name_t g_Name2{ "Name2"};
const Name_t g_Name3{ "Name3" };
const Name_t& TestClass::foo(const Spec_t& spec_)
{
static const std::map<Spec_t, Name_t > glmap1 =
{
{g_Spec1, g_Name1},
{g_Spec2, g_Name2}
};
std::cout << "Foo: Map size must be 2, but it is " << glmap1.size() << std::endl;
std::cout << "In FOO Name1 is " << g_Name1 << std::endl;
auto constIterator = glmap1.find(spec_);
if (constIterator == glmap1.cend())
{
std::cout << "Not found " << std::endl; // 3
return g_Name3;
}
else
{
std::cout << "Found " << constIterator->second << std::endl; // 4
return constIterator->second;
}
}
TestClass::TestClass(const Spec_t& j)
{
name = foo(j);
spec = j;
std::cout << "In CONSTRUCTOR name as global variable from map " << name << std::endl;
}
Another interesting thing is that 1 call 4(Found) and 2 calls 3(Not found) but the map is empty in both ways. Maybe it is because g_Spec1 didn't initialize at this time?
And I didn't get why the map inside is debugger is empty, but have size = 1
Token.h
#pragma once
#include <cinttypes>
#include <string>
#include <vector>
enum class Token
{
Type1,
Type2
};
struct TokenId
{
Token tok;
std::uint64_t val;
bool operator==(const TokenId& p_Other) const noexcept
{
return (tok == p_Other.tok && val == p_Other.val);
}
bool operator<(const TokenId& p_Other) const noexcept
{
if (tok < p_Other.tok) return true;
else if (tok == p_Other.tok)
{
return val < p_Other.val;
}
else return false;
}
};
using Name_t = std::string;
using Spec_t = std::vector<TokenId>;
This is not entirely surprising. Initialization of global objects is partially ordered. Definitions from a single file are ordered by their appearance within that file, but there is no order across files.
You might see unexpected results in a debugger, because using uninitialized variables is undefined behavior.
This is just one of the reasons why global variables are best avoided. In your case, just put that variable inside main().

Declare an object inside a C++ class [duplicate]

I'm beginning to learn C++. In the IDE codeblocks, this compiles:
#include <iostream>
using namespace std;
struct A {};
struct B {
A a;
}
void hi() {
cout << "hi" << endl;
}
int main() {
hi();
return 0;
}
But this doesn't:
struct B {
A a;
}
struct A {};
int main() {
hi();
return 0;
}
void hi() {
cout << "hi" << endl;
}
It gives me the errors:
error: 'A' does not name a type
error: 'hi' was not declared in this scope
Should class/function order matter in C++? I thought it doesn't. Please clarify the issue.
Yes, you must at least declare the class/function before you use/call it, even if the actual definition does not come until afterwards.
That is why you often declare the classes/functions in header files, then #include them at the top of your cpp file. Then you can use the classes/functions in any order, since they have already been effectively declared.
Note in your case you could have done this. (working example)
void hi(); // This function is now declared
struct A; // This type is now declared
struct B {
A* a; // we can now have a pointer to it
};
int main() {
hi();
return 0;
}
void hi() { // Even though the definition is afterwards
cout << "hi" << endl;
}
struct A {}; // now A has a definition

C++ Static members of a class are initialized after constructor

I have a problem with static members of a class not being initialized before the constructor. Am i doing something wrong? Is it a bug in G++ ?
Any workarounds?
g++ --version : (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
I am also using Eclipse as my IDE, but i just copy the static lib headers to /usr/include/StaticTestLib/InitTest.h and the library to /usr/lib/x86_64-linux-gnu/libStaticTestLib.a
Note this only happens if the object that holds the data is defined before main and the class is in a Static Library.
Static library header (the static library itself is named StaticTestLib):
InitTest.h
#include <iostream>
namespace StaticTestLib {
class notifier_header{
public:
notifier_header(){
std::cout<<"static var init"<<std::endl;
}
};
class InitTest {
public:
static notifier_header _header_notifier;
InitTest();
virtual ~InitTest();
};
}
Static library source file:
InitTest.cpp
#include "InitTest.h"
namespace StaticTestLib {
notifier_header InitTest::_header_notifier;
class notifier_cpp{
public:
notifier_cpp(){
std::cout<<"code before constructor"<<std::endl;
}
}_notifier_in_cpp;
InitTest::InitTest() {
std::cout<<"constructor"<<std::endl;
}
InitTest::~InitTest() {
std::cout<<"destructor"<<std::endl;
}
}
This program:
StaticTest.cpp
#include <iostream>
#include <StaticTestLib/InitTest.h>
StaticTestLib::InitTest test;
int main() {
std::cout << "program main" << std::endl;
std::cout << "program end" << std::endl;
return 0;
}
… outputs:
constructor
static var init
code before constructor
program main
program end
destructor
But this program:
#include <iostream>
#include <StaticTestLib/InitTest.h>
int main() {
std::cout << "program main" << std::endl;
StaticTestLib::InitTest test;
std::cout << "program end" << std::endl;
return 0;
}
… outputs:
static var init
code before constructor
program main
contructor
program end
destructor
My guess is that this is related to the order of static objects initialisation in different compilation units being undefined.
The second code snippet where you create a test object in your main is easy to explain. Static initialisation will always happen before any code is executed, so by the time you enter main, your notifier_header object is definitely created.
Now, when you create your test before main, you have two static objects. notifier_header object does not depend on your InitTest: it is scoped within that class, but it is stored in static memory. You seem to reference the notifier_header in your InitTest.cpp, which is a different compilation unit to main. A compiler is free to do static allocations in any order for those two units, provided that there is no interdependencies.
If your constructor depended on notifier_header, you could use it as a singleton. Create a function that returns an instance of a static object (headerInstance in the example below), and upon its call, the object will be created:
#include <iostream>
namespace StaticTestLib {
class notifier_header{
public:
notifier_header(){
std::cout<<"static var init"<<std::endl;
}
};
class InitTest {
public:
InitTest();
virtual ~InitTest();
notifier_header& headerInstance();
};
}
Static library source file (InitTest.cpp)
#include "InitTest.h"
namespace StaticTestLib {
class notifier_cpp{
public:
notifier_cpp(){
std::cout<<"code before constructor"<<std::endl;
}
}_notifier_in_cpp;
InitTest::InitTest() {
headerInstance();
std::cout<<"constructor"<<std::endl;
}
InitTest::~InitTest() {
std::cout<<"destructor"<<std::endl;
}
notifier_header& InitTest::headerInstance() {
static notifier_header _header_notifier; // will only be constructed once
return _header_notifier;
}
}
The output I get:
static var init
constructor
code before constructor
program main
program end
destructor

C++ Initialization of static function pointer array

I want to create a static function pointer array, so I can jump to a certain function regarding a received index. Like an index jumper.
So imagine a class like this:
Class A
{
private:
static void 1stFunction();
static void 2ndFunction();
static void(*functionPointer[20])(void);
};
Then I would like that functionPointer to get the value of the 1stFunction and 2ndFunction, and maybe even more.
So, how do I initialize it?
As far as I know, when a static member is declared, you can use it even before an instance is created. So I though, lets initialize that function pointer, so later I can call it like this
functionPointer[receivedIndex]();
So i tried to initilize it like this, in the same .h file
void (*A::functionPointer[])(void) =
{
A::1stFunction,
A::2ndFunction,
};
But the compiler gives me redifinition, it says it's already created.
So, pretty sure I'm missing something. I don't know though, if it is syntax or simply it is not possible to do it this way.
I know that function pointers to class's member functions are different than normal function pointers... But this is a static function, so I believe it doesn't belong to an instance and therefore it should work with normal function pointers.
Any help would be appreciated.
Thanks
The following would be a working example that probably achieves what you need.
You need C++11 for the initializer list.
It is a good practice to initialize the static member in the cpp file, as you don't want to have a definition of the static member everytime the header is included (this can lead to linking issues).
You can call callf with the desired index and have the corresponding function called, based on the initialization of the function pointer array.
The output of the program would be:
I am 2ndFunction
Header file
class A
{
private:
static void Function1();
static void Function2();
static void(*functionPointer[20])();
public:
static void callf(int index);
};
Implementation
#include <iostream>
#include "ex.h"
void(*A::functionPointer[20])() {
A::Function1,
A::Function2
};
void A::Function1() {
std::cout << "I am 1stFunction" << std::endl;
}
void A::Function2() {
std::cout << "I am 2ndFunction" << std::endl;
}
void A::callf(int index) {
A::functionPointer[index]();
}
int main(int argc, char const *argv[]) {
A::callf(1);
return 0;
}
Here you have a more modern C++ approach (C++14 needed)
I would advise you to explore lambda functions if you are not restricted to C++03.
#include <iostream>
#include <functional>
#include <vector>
class A {
public:
using f_type = std::function<void(void)>;
f_type f1 = []() { std::cout << "f0" << std::endl;};
f_type f2 = []() { std::cout << "f1" << std::endl;};
static void f3() { std::cout << "f3" << std::endl; }
std::vector<f_type> functions{f1, f2, f3};
};
int main() {
A a;
a.functions[0]();
a.functions[1]();
//adding custom lambda
a.functions.emplace_back([](){ std::cout << "custom f" << std::endl;});
a.functions[2]();
return 0;
}
you can add both functions and lambdas to your container.

How to share a static variable between C++ source files?

I don't know if it is possible to do this, but I have tried several ways and nothing seems to work. Basically I need to access the same static member from several files which include the same class definition.
// Filename: S.h
class S {
public:
static int foo;
static void change(int new_foo) {
foo = new_foo;
}
};
int S::foo = 0;
Then in a class definition (other .cpp file) I have:
// Filename: A.h
#include "S.h"
class A {
public:
void do_something() {
S::change(1);
}
};
And in another file:
// Filename: program.cpp
#include "S.h"
#include "A.h"
int main (int argc, char * const argv[]) {
A a = new A();
S::change(2);
std::cout << S::foo << std::endl;
a->do_something();
std::cout << S::foo << std::endl;
}
Now, I would expect the second function call to change the S::foo to 1, but the output is still:
2
Is the A.h file creating a local copy of the static class?
Thank you
Tommaso
This line:
int S::foo = 0;
needs to be in exactly one source file, not in the header. So move it from S.h to S.cpp.