Undefined reference to static variable when used with templates - new-operator

I have the below code which builds successfully when using the new , but undefined reference error when using std::make_unique.
Bar.h
#include <memory>
class Foo
{
public:
Foo(int c) : x(c) {}
private:
int x;
};
class Bar
{
public:
void setpointer()
{
fooPtr.reset( new Foo(x) ); // **** No linker error
// fooPtr = std::make_unique<Foo>(x); // **** Error : Undefined reference to Bar::x
}
static const unsigned int x = 3;
private:
std::unique_ptr<Foo> fooPtr{nullptr};
};
main.cpp
#include "Bar.h"
int main()
{
Bar bar;
bar.setpointer();
return 0;
}
I understand that definition of the static variable is missing and it can be solved by defining as static inline. But, the question is why there is no undefined reference when using new.

Related

C++ error: using temporary as lvalue when using member variable of container in dervied class

#include<iostream>
class acc{
public:
acc() { aa = 10;}
int aa;
};
class Derv;
class Base{
public:
Base() {}
int a;
virtual acc get_acc() {};
virtual void compare(Derv *v) {}
};
class Derv : public Base {
public:
acc acc_o;
Derv() {}
virtual acc get_acc();
virtual void compare(Derv *v) {
if(v->get_acc().aa = acc_o.aa) {
std::cout<<"Values Match\n";
}
}
};
acc Derv::get_acc() {
return acc_o;
}
int main() {
Base *d1 = new Derv();
Base *v = new Derv();
Derv *v1 = dynamic_cast<Derv *>(v);
d1->compare(v1);
std::cout<<d1->get_acc().aa<<std::endl;
return 0;
}
Above code is giving compiler error when compiled using gcc. Following is the compiler error:
accessor_test.cpp: In member function ‘virtual void Derv::compare(Derv*)’:
accessor_test.cpp:25:40: error: using temporary as lvalue [-fpermissive]
if(v->get_acc().aa = acc_o.aa) {
Not able to understand what is the reason for error? Can someone help me understand the error and possible fix for the same?

Find a unique_ptr to an inherited class object emplaced_back in a vector

I am trying to implement an Entity Component System (ECS) for my game. I have a base class "Component" (referred here as A) which is inherited by child class like HealthComponent(referred here as B), DamageComponent (referred here C)
#include <iostream>
#include <vector>
#include <algorithm>
#include <memory>
class A
{
public:
A() : VarA(10){}
int VarA;
const std::string ClassName = "A";
virtual void prnt(){ std::cout << "A class" << std::endl; }
};
class B : public A
{
public:
B() : VarB(20){}
int VarB;
const std::string ClassName = "B";
void prnt(){ std::cout << "B class" << std::endl; }
bool operator== (const B& other) const
{
return this->ClassName == other.ClassName;
}
};
class C : public A
{
public:
C() : VarC(30){}
int VarC;
const std::string ClassName = "C";
void prnt(){ std::cout << "C class" << std::endl; }
bool operator== (const B& other) const
{
return this->ClassName == other.ClassName;
}
};
int main()
{
std::vector<std::unique_ptr<A>> ObjVector;
std::vector<std::unique_ptr<A>>::iterator ObjIterator;
A* object1 = new B();
std::unique_ptr<A> bptr{object1};
ObjVector.emplace_back(std::move(bptr));
A* object2 = new C();
std::unique_ptr<A> cptr{object2};
ObjVector.emplace_back(std::move(cptr));
ObjIterator = std::find(ObjVector.begin(), ObjVector.end(), B);
return 0;
}
on compiling the code
-------------- Build: Debug in STL (compiler: GNU GCC Compiler)---------------
x86_64-w64-mingw32-g++.exe -Wall -g -std=c++11 -c C:\Users\admin\Desktop\code\C++\STL\main.cpp -o obj\Debug\main.o
x86_64-w64-mingw32-g++.exe -o bin\Debug\STL.exe obj\Debug\main.o
C:\Users\admin\Desktop\code\C++\STL\main.cpp: In function 'int main()':
C:\Users\admin\Desktop\code\C++\STL\main.cpp:58:66: error: expected primary-expression before ')' token
58 | ObjIterator = std::find(ObjVector.begin(), ObjVector.end(), B);
| ^
I tried using "new B()" and "(&B)" as the last parameter in std::find function but it still gave me errors. Please Help.
UPDATED CODE
#include <iostream>
#include <vector>
#include <algorithm>
#include <memory>
class A
{
public:
A() : VarA(10){}
int VarA;
const std::string ClassName = "A";
virtual std::string getClassName(){ return ClassName; }
};
class B : public A
{
public:
B() : VarB(20){}
int VarB;
const std::string ClassName = "B";
std::string getClassName() override { return ClassName; }
};
class C : public A
{
public:
C() : VarC(30){}
int VarC;
const std::string ClassName = "C";
std::string getClassName() override { return ClassName; }
};
int main()
{
std::vector<std::unique_ptr<A>> ObjVector;
std::vector<std::unique_ptr<A>>::iterator ObjIterator;
A* object1 = new B();
std::unique_ptr<A> bptr{object1};
ObjVector.emplace_back(std::move(bptr));
A* object2 = new C();
std::unique_ptr<A> cptr{object2};
ObjVector.emplace_back(std::move(cptr));
ObjIterator = std::find_if(ObjVector.begin(), ObjVector.end(),
[](const std::unique_ptr<A>& p)
{
return dynamic_cast<B*>(p.get()) != nullptr;
});
std::cout << (*ObjIterator)->VarB << std::endl;
return 0;
}
Your solution worked and i changed some of the code accordingly. It gives me access to methods common to all class, here "getClassName()". But on accessing class specific methods and variables (here VarB, which is specific to class B) it gives me the following error
-------------- Build: Debug in STL (compiler: GNU GCC Compiler)---------------
x86_64-w64-mingw32-g++.exe -Wall -g -std=c++11 -c C:\Users\admin\Desktop\code\C++\STL\main.cpp -o obj\Debug\main.o
x86_64-w64-mingw32-g++.exe -o bin\Debug\STL.exe obj\Debug\main.o
C:\Users\admin\Desktop\code\C++\STL\main.cpp: In function 'int main()':
C:\Users\admin\Desktop\code\C++\STL\main.cpp:55:34: error: 'class A' has no member named 'VarB'; did you mean 'VarA'?
55 | std::cout << (*ObjIterator)->VarB << std::endl;
| ^~~~
| VarA
Basically I cannot access the methods and variables that are not included in the base class. What am I doing wrong here?

OMNET++. Using custom message from imported dynamic library

I have two omnetpp projects: Lab1 and Lab2
From Lab1 .so library is created. Lab 2 is supposed to use this library. It is clear how to import and use modules declared in .ned-files. Problems begin when I try to use message-type from the library (Bitmessage).
bitmessage.msg from the library:
message Bitmessage {
bool bit;
}
sSource.h in Lab2:
#ifndef SSOURCE_H_
#define SSOURCE_H_
#include <omnetpp.h>
#include "bitmessage_m.h"
class sSource : public cSimpleModule
{
protected:
virtual void initialize();
virtual void handleMessage(cMessage *msg);
private:
double p;
};
Define_Module(sSource);
#endif /* SSOURCE_H_ */
sSource.cc - source-file in Lab2 which is suppose to use bitmessage:
#include <sSource.h>
/*virtual*/ void sSource::initialize()
{
p = par("p").doubleValue();
}
/*virtual*/ void sSource::handleMessage(cMessage *msg)
{
if (msg->getArrivalGate() == gate("in"))
{
delete msg;
Bitmessage* bit_msg = new Bitmessage(); // **(!!!)here is error**
int num_outs = this->gateSize("out");
for (int i = 0; i < num_outs; ++i)
{
send(bit_msg->dup(), "out", i);
}
delete bit_msg;
}
else
{
delete msg;
}
}
The error is following:
undefined reference to `Bitmessage::Bitmessage(char const*, int)'
How to deal with it? Maybe the problem is that compiler can't interpret .msg-file from the library?

Undefined reference to xx::xx()

Believe me when I tell you that I searched online, but did not find the answer.
I have 5 files:
main.cpp
Game.cpp
Game.hpp
Window.cpp
Window.hpp
The content is below :
#include "Window.hpp"
#include "Game.hpp"
int main()
{
// Program entry point
Game game;
while (!game.GetWindow()->IsDone()){
// game loop here
game.HandleInput();
game.Update();
game.Render();
}
return 0;
}
This is the Game.cpp
#include "Window.hpp"
class Game {
public:
Game(): m_window("Chapter 2", sf::Vector2u(800,600)) {
m_mushroomTexture.loadFromFile("images.png");
m_mushroom.setTexture(m_mushroomTexture);
}
~Game(){}
void HandleInput() {
}
void Update() {
m_window.Update();
MoveMushroom();
}
void Render() {
m_window.BeginDraw();
m_window.Draw(m_mushroom);
m_window.EndDraw();
}
// Getting a point to the window
Window* GetWindow(){
}
private:
void MoveMushroom(){
sf::Vector2u l_windSize = m_window.GetWindowSize();
sf::Vector2u l_textSize = m_mushroomTexture.getSize();
if ((m_mushroom.getPosition().x > l_windSize.x - l_textSize.x and m_increment.x > 0) or \
(m_mushroom.getPosition().x < 0 and m_increment.x < 0)) {
m_increment.x = -m_increment.x;
}
if ((m_mushroom.getPosition().y > l_windSize.y - l_textSize.y and m_increment.y > 0) or \
(m_mushroom.getPosition().y < 0 and m_increment.y < 0)) {
m_increment.y = -m_increment.y;
}
m_mushroom.setPosition( m_mushroom.getPosition().x + m_increment.x, m_mushroom.getPosition().y + m_increment.y);
}
Window m_window;
sf::Texture m_mushroomTexture;
sf::Sprite m_mushroom;
sf::Vector2i m_increment;
};
Game.hpp
#pragma once
#include "Window.hpp"
#include <SFML/Graphics.hpp>
class Game {
public:
Game();
~Game();
void HandleInput();
void Update();
void Render();
// Getting a point to the window
Window* GetWindow();
private:
void MoveMushroom();
Window m_window;
sf::Texture m_mushroomTexture;
sf::Sprite m_mushroom;
sf::Vector2i m_increment;
};
Window.cpp
#include <SFML/Graphics.hpp>
#include <string>
class Window {
public:
// constructor
Window() {Setup("Window", sf::Vector2u(640,480));}
// we have 2 constructors because there 2 ways to instantiate a class
Window(const std::string& l_title, const sf::Vector2u& l_size) {
Setup(l_title, l_size);
}
~Window() { Destroy(); }
void BeginDraw(){
m_window.clear(sf::Color::Black);
}
void EndDraw(){
m_window.display();
}
void Update(){
sf::Event event;
while (m_window.pollEvent(event)) {
if (event.type == event.Closed) {
m_isDone = true;
} else if (event.type == sf::Event::KeyPressed and event.key.code == sf::Keyboard::F5){
ToggleFullscreen();
}
}
}
bool IsDone(){
return m_isDone;
}
bool IsFullscreen(){
return m_isFullscreen;
}
sf::Vector2u GetWindowSize() {
return m_windowSize;
}
void ToggleFullscreen(){
m_isFullscreen = !m_isFullscreen;
Destroy();
Create();
}
void Draw(sf::Drawable& l_drawable){
m_window.draw(l_drawable);
}
private:
void Setup(const std::string& l_title, const sf::Vector2u& l_size) {
m_windowTitle = l_title;
m_windowSize = l_size;
m_isFullscreen = false;
m_isDone = false;
Create();
}
void Destroy(){
m_window.close();
}
void Create() {
// the same as
// if (m_isFullscreen) {
// auto_style = sf::Style::Fullscreen;
// } else {
// auto_style = sf::Style::Default;
// }
auto style = (m_isFullscreen ? sf::Style::Fullscreen : sf::Style::Default);
m_window.create({m_windowSize.x, m_windowSize.y, 32}, m_windowTitle, style);
}
sf::RenderWindow m_window;
sf::Vector2u m_windowSize;
std::string m_windowTitle;
bool m_isDone;
bool m_isFullscreen;
};
Window.hpp
#pragma once
#include <SFML/Graphics.hpp>
#include <string>
class Window {
public:
// constructor
Window();
// we have 2 constructors because there 2 ways to instantiate a class
Window(const std::string& l_title, const sf::Vector2u& l_size);
~Window();
void BeginDraw();
void EndDraw();
void Update();
bool IsDone();
bool IsFullscreen();
sf::Vector2u GetWindowSize();
void ToggleFullscreen();
void Draw(sf::Drawable& l_drawable);
private:
void Setup(const std::string& l_title, const sf::Vector2u& l_size);
void Destroy();
void Create();
sf::RenderWindow m_window;
sf::Vector2u m_windowSize;
std::string m_windowTitle;
bool m_isDone;
bool m_isFullscreen;
};
The problem is that when i try to build my project i get a linker error.
/tmp/ccxbe5nA.o: In function `main':
main.cpp:(.text+0x26): undefined reference to `Game::Game()'
main.cpp:(.text+0x35): undefined reference to `Game::GetWindow()'
main.cpp:(.text+0x3d): undefined reference to `Window::IsDone()'
main.cpp:(.text+0x53): undefined reference to `Game::HandleInput()'
main.cpp:(.text+0x62): undefined reference to `Game::Update()'
main.cpp:(.text+0x71): undefined reference to `Game::Render()'
main.cpp:(.text+0x87): undefined reference to `Game::~Game()'
main.cpp:(.text+0xac): undefined reference to `Game::~Game()'
collect2: error: ld returned 1 exit status
I am compiling first with the following command :
g++ -std=c++11 -c main.cpp Window.cpp Game.cpp
No errors during the compilation stage. When I try to link it, I get the error message from above. The command used is this :
g++ main.o Game.o Window.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system
By defining the same class differently in different places, your program violates One Definition Rule:
[basic.def.odr]/5 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 named D defined in more than one translation unit, then
— each definition of D shall consist of the same sequence of tokens; and...
Emphasis mine.
Remove class definition from Game.cpp, only leave member function definitions, like this:
Game::Game(): m_window("Chapter 2", sf::Vector2u(800,600)) {...}
void Game::Update() {...}
// and so on for other members
And similarly for Window.
You define each class twice, which is incorrect.
In your .cpp files it needs to provide definitions for functions declared but not defined in the headers.
E.g., Windows.cpp should include Windows.hpp and contain:
bool Windows::IsDone() {
return m_isDone;
}

Index with boost multi_index

How can I index a boost::multi_index container using a member function of class(that is being stored in the multi_index) that returns a constant reference of another class?
The error I get is :
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'RetClass (__thiscall StoreMe::* )(void) const'
Edit1:
This is a complete verifiable piece of similar code I created which has the same error,
#include "stdafx.h"
#include<multi_index_container.hpp>
#include<boost/multi_index/hashed_index.hpp>
#include<boost/multi_index/mem_fun.hpp>
class RetClass
{
int a, b;
};
class StoreMe
{
RetClass ex;
public:
void setId(RetClass a) {
ex = a;
};
virtual const RetClass& getId() const { return ex; }
};
typedef boost::multi_index_container<
StoreMe,
boost::multi_index::indexed_by<
boost::multi_index::hashed_non_unique<boost::multi_index::const_mem_fun<StoreMe, RetClass, &StoreMe::getId> >
>
> mi_storeMe;
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
TIA
-R
Use boost::multi_index::const_mem_fun.
Edited after OP's additional information: the return type specified in const_mem_fun has to be exactly the same as that of the function you want to use for indexing. Note the differences in your current code:
virtual const RetClass& getId() const;
const_mem_fun<StoreMe, RetClass, &StoreMe::getId>
So, change the const_mem_fun part as follows:
const_mem_fun<StoreMe, const RetClass&, &StoreMe::getId>

Resources