I'm attempting to create a list of objects using the variant boost.
#include <string>
#include <list>
#include <iostream>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
class CSquare;
class CRectangle {
public:
CRectangle();
};
class CSquare {
public:
CSquare();
};
int main()
{ typedef variant<CRectangle,CSquare, bool, int, string> object;
list<object> List;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
List.push_back(new CSquare());
List.push_back(new CRectangle ());
cout << "List Size is: " << List.size() << endl;
return 0;
}
Unfortunately, the following error is produced:
/tmp/ccxKh9lz.o: In function `main':
testing.C:(.text+0x170): undefined reference to `CSquare::CSquare()'
testing.C:(.text+0x203): undefined reference to `CRectangle::CRectangle()'
collect2: ld returned 1 exit status
I realise that everything would be fine if i used the form:
CSquare x;
CRectangle y;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
List.push_back(x);
List.push_back(y);
But i would like to avoid that form if at all possible, since i would like to keep my objects unnamed. This is an important requirement for my system - is there any way i can avoid using named objects?
Just need to change a few things and it works:
#include <iostream>
#include <list>
#include <string>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
class CRectangle
{
public:
CRectangle() {}
};
class CSquare
{
public:
CSquare() {}
};
int main()
{
typedef variant<CRectangle, CSquare, bool, int, string> object;
list<object> List;
List.push_back(string("Hello World!"));
List.push_back(7);
List.push_back(true);
List.push_back(CSquare());
List.push_back(CRectangle());
cout << "List Size is: " << List.size() << endl;
return 0;
}
Specifically, you needed to define the CRectangle and CSquare constructors (that's why you were getting a linker error) and to use CSquare() rather than new CSquare() etc. Also, "Hello World!" has type const char *, so you need to write string("Hello World!") when passing it to push_back or it will get implicitly converted to bool here (not what you want).
Instead of List.push_back(new CSquare()); just write
List.push_back(CSquare());
And also write defination of your constructor
You forget to implement the constructors CRectangle::CRectangle() and CSquare::CSquare().
Either implement them somewhere outside the class such as:
CRectangle::CRectangle()
{
// :::
};
... or implement them inside the class:
class CRectangle {
public:
CRectangle()
{
// :::
}
};
... or remove the constructor declarations altogether:
class CRectangle {
public:
};
Related
I have a class that has a constructor. I now need to make a map with it as a value how do I do this? Right now without a constructor I do.
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
};
int main()
{
map<int,testclass> thismap;
testclass &x = thismap[2];
}
If I added a constructor with arguments how would I add them to the map? I basically need to do
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
testclass(int arg) {
x = arg;
}
};
int main()
{
map<int,testclass> thismap;
testclass &x = thismap[2];
}
This obviously wouldn't work since it requires an argument but I can't figure a way of doing this.
This is how you can add items of your own class to your map.
Note : I used a string in testclass to better show difference
between key and value/class.
#include <iostream>
#include <string>
#include <map>
class testclass
{
public:
explicit testclass(const std::string& name) :
m_name{ name }
{
};
const std::string& name() const
{
return m_name;
}
private:
std::string m_name;
};
int main()
{
std::map<int, testclass> mymap;
// emplace will call constructor of testclass with "one", and "two"
// and efficiently place the newly constructed object in the map
mymap.emplace(1, "one");
mymap.emplace(2, "two");
std::cout << mymap.at(1).name() << std::endl;
std::cout << mymap.at(2).name() << std::endl;
}
Using std::map::operator[] requires that the mapped type is default-constructible, since it must be able to construct an element if one doesn't already exist.
If your mapped type is not default-constructible, you can add elements with std::map::emplace, but you still can't use std::map::operator[] to search, you will need to use std::map::find() or so.
That's a rather obvious feature of std::map (and very similar other std containers). Some of their operations require specific type requirements for good reasons.
There is no problem to create such a map as you suggest in the first place, however, you are restricted to method calls that do not require potential default construction. The operator[] is such a method, since in the case the element is not found, it is created. That is what does not work in your example. Just use other methods with little impact on the map usage and you can still succeed:
#include <iostream>
#include <map>
using namespace std;
class testclass {
public:
int x = 1;
testclass(int arg) {
x = arg;
}
};
int main()
{
map<int,testclass> thismap;
thismap.insert( {2, testclass(5)} );
auto element2 = thismap.find(2);
if (element2 != thismap.end()) {
testclass& thiselement = element2->second;
cout << "element 2 found in map, value=" << thiselement.x << endl;
}
auto element5 = thismap.find(5);
if (element5 == thismap.end()) {
cout << "no element with key 5 in thismap. Error handling." << endl;
}
}
Main issue: avoid operator[].
Note:
Looking at the other very good answers, there are a lot of methods that can be used without default construction. There is not "right" or "wrong" since this simply depends on your application. at and emplace are prime examples that are highly advisable.
This question already has an answer here:
Does not name a type
(1 answer)
Closed 2 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I'm using iostream and map. When I try to set the functions, they throw an error.
My code:
#include "string"
#include "iostream"
#include "map"
using namespace std;
class myClass {
map<string, string> Map;
Map["Ziv"] = "Sion";
cout << Map["Ziv"];
};
My error:
error: 'Map' does not name a type
error: 'cout' does not name a type
Why I can't use iostream and cout?
Why I can't use iostream and cout?
Because a class cannot (directly) contain expression statements. It can contain only member declarations.
Expression statements can only be within functions. This would be correct for example:
class main {
map<string, string> Map;
void example_function() {
Map["Ziv"] = "Sion";
cout << Map["Ziv"];
}
};
you can't have a C++ progran without the main function so please create int main(){}. And change the double quotes in the #include directives to angle brackets like below:
#include <string>
#include <iostream>
#include <map>
using namespace std;
class myClass {
public:
int myFunc();
};
myClass :: int myFunc(){
map<string, string> Map;
Map["Ziv"] = "Sion";
cout << Map["Ziv"];
}
int main(){
myClass myclass;
myclass.myFunc();
return 0;
}
Please consider i am a beginner and forgive my mistakes if any.
In object oriented languages, like C++, you can't write expressions/statements in a class. You may want to use a function. Example:
#include<iostream>
using std::cout;
class Example {
public:
void sayHello() {
cout << "Hello!";
}
}
int main() {
new Example().sayHello(); // Prints Hello!
}
You have to enter the cout in a function, inside the class you can't execute functions, you just can describe them or variables / objects.
Class is an Entity which contains related data members and the operations to modify or access those data members. No expression can be executed within the class. It does not make an sense to do something that you can not access. Because the only way to access and modify something are operations.
Yes in case if you want to print something when the class object is created, you can do that in Constructor. May be this is what you want to do:
#include <map>
#include <iostream>
#include <string>
class myClass {
private:
std::map<std::string, std::string> Map;
public:
myClass(const std::string& key, const std::string& value){
Map[key] = value;
std::cout << value;
}
};
int main(){
myClass cls("Ziv", "Sion");
}
I am trying to make a class with two constructors. One that is a default constructor, the other calling the parameterized constructor. I get a compiler error that tells me that I cannot use move on the object just created and I sort of understand that it doesn't like to do that, because there is no real assignment here.
How can I achieve the right behavior? I am trying to avoid writing two constructors that initialize the variables. An initialization function might work, but then I would have to fill the body of the constructors and I was trying to come up with a neat solution like shown below.
#include <string>
#include <iostream>
#include <memory>
using namespace std;
class Foo
{
public:
Foo(unique_ptr<int>& number) : m_number(move(number))
{
}
Foo() : Foo(make_unique<int>(54))
{
}
void print()
{
cout << m_number << endl;
}
private:
unique_ptr<int> m_number;
};
int main()
{
Foo f;
f.print();
return 0;
}
main.cpp:18:33: error: invalid initialization of non-const reference
of type ‘std::unique_ptr&’ from an rvalue of type
‘std::_MakeUniq::__single_object {aka std::unique_ptr}’
Foo() : Foo(make_unique(54))
I decided to go for an rvalue constructor. This seems to resolve the issue for me.
#include <string>
#include <iostream>
#include <memory>
using namespace std;
class Foo
{
public:
// rvalue constructor so that we can move the unique_ptr.
Foo(unique_ptr<int>&& number) : m_number(move(number))
{
}
Foo() : Foo(make_unique<int>(54))
{
}
void print()
{
cout << *m_number << endl;
}
private:
unique_ptr<int> m_number;
};
int main()
{
Foo f;
f.print();
unique_ptr<int> a = make_unique<int>(33);
Foo f2(move(a)); // important to do a move here, because we need an rvalue.
f2.print();
return 0;
}
I need help with passing a function pointer on C++. I can't linkage one function for a class to other function. I will explain. Anyway I will put a code resume of my program, it is much larger than the code expose here but for more easier I put only the part I need to it works fine.
I have one class (MainSystem) and inside I have an object pointer to the other class (ComCamera). The last class is a SocketServer, and I want when the socket received any data, it sends to the linkage function to MainSystem.
ComCamera is a resource Shared with more class and I need to associate the functions ComCamera::vRecvData to a MainSystem::vRecvData or other function of other class for the call when receive data and send de data to the function class associate.
Can Anyone help to me?
EDDITED - SOLUTION BELOW
main.cpp
#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <cmath>
#include <string.h>
#include <stdio.h>
#include <exception>
#include <unistd.h>
using std::string;
class ComCamera {
public:
std::function<void(int, std::string)> vRecvData;
void vLinkRecvFunction(std::function<void(int, std::string)> vCallBack) {
this->vRecvData = vCallBack;
}
void vCallFromCamera() {
this->vRecvData(4, "Example");
};
};
class MainSystem {
private:
ComCamera *xComCamera;
public:
MainSystem(ComCamera *xComCamera) {
this->xComCamera = xComCamera;
this->xComCamera->vLinkRecvFunction([this](int iChannelNumber, std::string sData) {vRecvData(iChannelNumber, sData); });
}
void vRecvData(int iNumber, string sData) {
std::cout << "RECV Data From Camera(" + std::to_string(iNumber) + "): " << sData << std::endl;
};
};
int main(void) {
ComCamera xComCamera;
MainSystem xMainSystem(&xComCamera);
xComCamera.vCallFromCamera();
return 0;
}
Output will be:
MainSystem RECV Data From Camera(4): Example
You can have ComCamera::vRecvData be of type std::function<void(int, std::string)> and then have ComCamera::vLinkRecvFunction() be like this:
void ComCamera::vLinkRecvFunction(std::function<void(int, std::string)> callBack)
{
this->vRecvData = callBack;
}
and have MainSystem constructor be like this:
MainSystem::MainSystem(ComCamera *xComCamera)
{
using namespace std::placeholders;
this->xComCamera = xComCamera;
this->xComCamera->vLinkRecvFunction([this](int iNumber, std::string sData){vRecvData(number, sData);});
}
Still though the original question has way too much code to go through friend.
Here what you want :
#include<iostream>
using std::cout;
class A; //forward declare A
class B{
public:
void (A::*ptr)(int x); //Only declare the pointer because A is not yet defined.
};
class A{
public:
void increase_by(int x){
a+=x;
} // this function will be pointed by B's ptr
int a = 0; // assume some data in a;
B b; // creating B inside of A;
void analyze(int y){
(*this.*(b.ptr))(y);
} // Some function that analyzes the data of A or B; Here this just increments A::a through B's ptr
};
int main(){
A a; // creates A
cout<<a.a<<"\n"; // shows initial value of a
a.b.ptr = &A::increase_by; // defines the ptr that lies inside of b which inturns lies inside a
a.analyze(3); // calls the initialize method
(a.*(a.b.ptr))(3); // directly calls b.ptr to change a.a
cout<<a.a; // shows the value after analyzing
return 0;
}
Output will be :
0
6
I still don't get why would you do something like this. But maybe this is what you wanted as per your comments.
To know more read this wonderful PDF.
I am trying to write a class which defines a std::map. The comparator of the map must be a function pointer. The function pointer can be passed to the class as an argument in class's constructor.
Below is the code I wrote:
#include <iostream>
#include <map>
#include <string>
#include <functional>
typedef std::function<bool(std::string x, std::string y)> StrComparatorFn;
bool FnComparator(std::string x, std::string y) {
return strtoul(x.c_str(), NULL, 0) < strtoul(y.c_str(), NULL, 0);
}
class MyClass {
public:
MyClass(StrComparatorFn fptr):fn_ptr(fptr){};
void Insert() {
my_map.insert(std::pair<std::string, std::string>("1", "one"));
my_map.insert(std::pair<std::string, std::string>("2", "two"));
my_map.insert(std::pair<std::string, std::string>("10", "ten"));
}
void Display() {
for (auto& it : my_map) {
std::cout << it.first.c_str() << "\t => " << it.second.c_str() << "\n";
}
}
private:
StrComparatorFn fn_ptr;
std::map<std::string, std::string, StrComparatorFn> my_map(StrComparatorFn(fn_ptr));
};
int main() {
MyClass c1(&FnComparator);
c1.Insert();
c1.Display();
}
I am getting a compile error in Insert:
error: '((MyClass*)this)->MyClass::my_map' does not have class type
my_map.insert(std::pair<std::string, std::string>("1", "one"));
Any solution to this issue?
That line
std::map<std::string, std::string, StrComparatorFn> my_map(StrComparatorFn(fn_ptr));
has a problem known as the most vexing parse. Basically, everything that can be interpreted as a function, will be:
Foo f(); //f is a function! Not a variable
In your case, my_map is parsed as a declared function without a definition. Using curly braces instead of curved braces will solve the problem, as list initialization can never be interpreted as a function:
std::map<std::string, std::string, StrComparatorFn> my_map{ StrComparatorFn(fn_ptr) };