I can't find where std::option comes useful - stdoptional

I found above code in this link and it tells that this example where std::option nicely fits!
class UserRecord
{
public:
UserRecord(const std::string& name, std::optional<std::string> nick, std::optional<int> age)
: mName{ name }, mNick{ nick }, mAge{ age }
{
}
friend std::ostream& operator << (std::ostream& stream, const UserRecord& user);
private:
std::string mName;
std::optional<std::string> mNick;
std::optional<int> mAge;
};
std::ostream& operator << (std::ostream& os, const UserRecord& user)
{
os << user.mName << ' ';
if (user.mNick) {
os << *user.mNick << ' ';
}
if (user.mAge)
os << "age of " << *user.mAge;
return os;
}
int main()
{
UserRecord tim{ "Tim", "SuperTim", 16 };
UserRecord nano{ "Nathan", std::nullopt, std::nullopt };
std::cout << tim << "\n";
std::cout << nano << "\n";
}
I created another one without optional which is below and i find it more easier than one which uses std::option.
I think the second version is more readable because no need to use std::nullopt
class UserRecord
{
public:
UserRecord(const std::string& name, std::string nick = "", int age = 0)
: mName{ name }, mNick{ nick }, mAge{ age }
{
}
friend std::ostream& operator << (std::ostream& stream, const UserRecord& user);
private:
std::string mName;
std::string mNick;
int mAge;
};
std::ostream& operator << (std::ostream& os, const UserRecord& user)
{
os << user.mName << ' ';
if (user.mNick != "") {
os << user.mNick << ' ';
}
if (user.mAge != 0)
os << "age of " << user.mAge;
return os;
}
int main()
{
UserRecord tim{ "Tim", "SuperTim", 16 };
UserRecord nano{ "Nathan" };
std::cout << tim << "\n";
std::cout << nano << "\n";
}
So, why do we need to use optional in general and specially in this case?

Related

Input Element Causing Errors

My class is currently studying Classes and I'm attempting to complete my assignment due tomorrow. I have most of it done, however, for some reason the address input won't let me input any letters only numbers.
I can't figure out what I'm doing wrong here and would appreciate help in figuring out if I need to change something.
#include <iostream>
using namespace std;
class personalData
{
private:
string name;
string address;
int age;
string phNumber;
public:
void setName()
{
cout << "Enter name: ";
cin >> name;
}
string getName()
{
return name;
}
void setAddress()
{
cout << "Enter address: ";
cin >> address;
}
string getAddress()
{
return address;
}
void setAge()
{
cout << "Enter age: ";
cin >> age;
}
int getAge()
{
return age;
}
void setPhone()
{
cout << "Enter phone number: ";
cin >> phNumber;
}
string getPhone()
{
return phNumber;
}
void displayData()
{
cout << "\nName: " << getName() << endl;
cout << "Address " << getAddress() << endl;
cout << "Age: " << getAge() << endl;
cout << "Phone: " << getPhone() << endl;
}
};
int main()
{
personalData person1;
personalData person3;
personalData person2;
person1.setName();
person1.setAddress();
person1.setAge();
person1.setPhone();
person1.getAddress();
cout << "\n";
person2.setName();
person2.setAddress();
person2.setAge();
person2.setPhone();
person2.getAddress();
cout << "\n";
person3.setName();
person3.setAddress();
person3.setAge();
person3.setPhone();
person3.getAddress();
cout << "\n";
cout << "Person1 details: ";
person1.displayData();
cout << "Person2 details: ";
person2.displayData();
cout << "Person3 details: ";
person3.displayData();
return 0;
}
Here is what it looks like if you input both numbers and letters:
And here is what happens if you only input numbers:

C++ class casting

Guys I am trying to create an object that can instantiate the other types that inherit it:
#include <iostream>
#include <cstdlib>
class Animal {
public:
char *nome;
Animal (char *nome) {
this->nome = nome;
}
};
class Cachorro : public Animal {
public:
bool enterraOsso;
Cachorro (char* nome, bool enterraOsso) : Animal(nome) {
this->enterraOsso = enterraOsso;
}
};
class Passaro : public Animal {
public:
bool voar;
Passaro (char* nome, bool voar) : Animal(nome) {
this->voar = voar;
}
};
int main() {
Animal *animal;
animal = new Cachorro("Scooby", true);
std::cout << animal->nome << ", " << animal->enterraOsso << std::endl;
animal = new Passaro("Piopio", false);
std::cout << animal->nome << ", " << animal->voar << std::endl;
return 0;
}
The idea is to access the subclass attributes from the superclass also.
I don't know if this is a cast or polymorphism, in Java I know it is possible, but can't do it in C++.
Thank you for all your help.
You can, it is bad design though for a Base class to know about its children:
int main() {
Animal *animal;
animal = new Cachorro("Scooby", true);
Cachorro * c = reinterpret_cast<Cachorro*>(animal);
std::cout << animal->nome << ", " << c->enterraOsso << std::endl;
animal = new Passaro("Piopio", false);
Passaro * p = reinterpret_cast<Passaro*>(animal);
std::cout << animal->nome << ", " << p->voar << std::endl;
}

Template class method error "no 'void Pair<T1, T2>::display()' member function Pair declared in class"

I'm not sure if my syntax is incorrect. I am getting "no 'void Pair T1, T2::display()' member function Pair declared in class" as well as "no matching function for call to ‘Pair std::basic_string char, std::char_traits char" Here is the header file:
#ifndef PAIR_H
#define PAIR_H
#include <iostream>
#include <string>
using namespace std;
template <typename T1, typename T2 >
class Pair
{
private:
T1 t1;
T2 t2;
public:
Pair(const T1 & t1,const T2 & t2) : t1(t1), t2(t2) {};
T1 getFirst() const { return t1; };
T2 getSecond() const { return t2; };
//setters
void setFirst(const T1 & value) { t1 = value; };
void setSecond(const T2 & value) { t2 = value; };
};
template <typename T1, typename T2>
void Pair<T1,T2> :: display()
{
cout << t1 << " - " << t2 << endl;
}
#endif // PAIR_H
and this is the driver file.
#include <iostream>
#include <string>
using namespace std;
#include "pair.h"
int main()
{
string first;
cout << "Please enter a first name: ";
cin >> first;
string last;
cout << "Please enter a last name: ";
cin >> last;
Pair<string, string> fullName;
fullName.setFirst(first);
fullName.setSecond(last);
cout << "The first name is: " << fullName.getFirst() << endl;
cout << "The last name is: " << fullName.getSecond() << endl;
cout << "The complete pair is: ";
fullName.display();
cout << endl << endl;
int num1;
cout << "Please enter a number: ";
cin >> num1;
int num2;
cout << "Please enter another number: ";
cin >> num2;
Pair<int, int> numbers;
numbers.setFirst(num1);
numbers.setSecond(num2);
cout << "The first number is: " << numbers.getFirst() << endl;
cout << "The second number is: " << numbers.getSecond() << endl;
cout << "The complete pair is: ";
numbers.display();
cout << endl << endl;
string name;
cout << "Please enter a name: ";
cin >> name;
int score;
cout << "Please enter a score: ";
cin >> score;
Pair<string, int> grade;
grade.setFirst(name);
grade.setSecond(score);
cout << "The name is: " << grade.getFirst() << endl;
cout << "The score is: " << grade.getSecond() << endl;
cout << "The complete pair is: ";
grade.display();
cout << endl << endl;
return 0;
}
Yes, your syntax is incorrect.
1) display() is a member of Pair, so you must declare it inside the class.
You can add this declaration line in the public section
void display ();
or you can define display() inside the class (deleting the definition outside) [I added the const modifier]
void display () const { cout << t1 << " - " << t2 << endl; }
1 bis)
I suggest you to define the operator<< (output operator) for class Pair; something like, inside public, this
friend ostream & operator<< (ostream & os, Pair const & p)
{ return os << '(' << p.t1 << ',' << p.t2 << ')'; }
so you can simply output a pair like this
cout << fullName << endl;
2) You don't define a default constructor (without arguments), so you should define you pairs in this way
Pair<string, string> fullName("", "");
Pair<int, int> numbers(0, 0);
Pair<string, int> grade("", 0);
or, avoiding the following setFirst() and setSecond()
Pair<string, string> fullName(first , last);
Pair<int, int> numbers(num1, num2);
Pair<string, int> grade(name, score);
3) I don't know if you know it but there is a standard std::pair class (#include <utility>).
4) You should use che c++ tag for a question like this
5) Sorry for my bad English

Function Pointers in C++ Class Files

I've been trying to work with function pointers for quite a bit now, and to no avail. I've been working with a few friends to create a C++ 11 library to make creating ASCII games easier, and I've personally been working on creating a menu class. The beef of the class is complete, but one issue - I can't get the buttons to call functions. I always get the error:
terminate called after throwing an instance of 'std::bad_function_call'
what(): bad_function_call
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Obviously the error lies somewhere in the pointers, but I can't solve it for the life of me. Thanks for the help in advance.
Menu.h
#ifndef MENU_H
#define MENU_H
using namespace std;
#include <functional>
#include <string>
#include <map>
class Menu {
public:
int numberOfOptions;
map<int, string> options;
int currentSelection;
string title;
Menu();
Menu(int initialNumberOfOptions, map<int, string> initialOptions, int initialSelection);
void display();
void waitForInput();
void attachOptionAction(int option, void (*function)());
private:
map<int, void (*std::function<void()>)> optionActions;
void executeOptionAction(int option);
};
#endif
Menu.cpp
#include "Menu.h"
#include <windows.h>
#include <iostream>
#include <conio.h>
Menu::Menu(int initialNumberOfOptions, map<int, string> initialOptions, int initialSelection) {
title = "";
numberOfOptions = initialNumberOfOptions;
options = initialOptions;
currentSelection = initialSelection;
}
void Menu::display() {
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), {0, 0});
for(int i = 0; i < 10; i++) {
cout << " " << endl;
}
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), {0, 0});
if(title != "") {
cout << title << endl << endl;
}
for(int i = 0; i < numberOfOptions; i++) {
if(i == currentSelection - 1) {
cout << "[ " << options[i] << " ]" << endl;
} else {
cout << options[i] << endl;
}
}
waitForInput();
}
void Menu::waitForInput() {
char input;
while(!kbhit());
input = getch();
if(input == 72 && currentSelection > 1) {
currentSelection--;
} else if (input == 80 && currentSelection < numberOfOptions) {
currentSelection++;
} else if (input == 13) {
if(currentSelection == 1) {
executeOptionAction(1);
}
return;
}
display();
}
void Menu::attachOptionAction(int option, std::function<void()> function) {
optionActions[option] = function;
}
void Menu::executeOptionAction(int option) {
(optionActions[option])();
}
test.cpp
#include "Menu.h"
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <map>
void test() {
cout << "Hello, World!";
}
int main() {
map<int, string> options;
options[0] = "Play";
options[1] = "Help";
options[2] = "Quit";
Menu menu(3, options, 1);
menu.title = "ASCII Game Library 2015";
menu.display();
void (*actionPointer)() = NULL;
menu.attachOptionAction(1, (*actionPointer));
return 0;
}
This is wrong. I'm not even sure what's that supposed to be.
map<int, void (*std::function<void()>)> optionActions;
It should be:
map<int, std::function<void()>> optionActions;
This here is also wrong. It would be correct if you hadn't imported std into your current namespace.
void attachOptionAction(int option, void (*function)());
It should be:
void attachOptionAction(int option, const std::function<void()> & action);
This here is also wrong. You can't name your argument function after you imported std into your namespace.
void Menu::attachOptionAction(int option, std::function<void()> function)
It should be:
void Menu::attachOptionAction(int option, const std::function<void()> & action)
This here is also wrong. You don't check if the function exists or that a valid function pointer was assigned to it. Which you haven't.
(optionActions[option])();
It should be:
// Attempt to find the action!
map<int, std::function<void()>>::iterator action = optionActions.find(option);
// Did we find anything?
if (action == optionActions.end())
{
return;
}
// Is the function assigned to this action valid?
if (action->second)
{
action->second();
}
You are attaching a null function pointer to an action and try to call it. And since there's no validation it does exactly that. Which is why you get that exception:
void (*actionPointer)() = NULL;
menu.attachOptionAction(1, (*actionPointer));
But I'm not even sure how even managed to compile it :/
EDIT:
I hope you can find this example to be informative on what you're looking for.
#include <map>
#include <string>
#include <cstdlib>
#include <iostream>
#include <functional>
class Menu
{
protected:
typedef std::function<int (Menu &)> Callback;
typedef std::map<int, Menu> SubMenus;
public:
Menu()
: m_Id(0), m_Name(""), m_Handler(nullptr)
{
}
Menu(int id, const std::string & name, Callback clbk)
: m_Id(id), m_Name(name), m_Handler(clbk)
{
}
Menu & operator [] (int id)
{
return m_Childrens.at(id);
}
int Enter()
{
int result = 0;
if (m_Handler)
result = m_Handler(*this);
return result;
}
void Insert(const Menu & menu)
{
m_Childrens[menu.m_Id] = menu;
}
void Insert(int id, const std::string & name, Callback clbk)
{
m_Childrens[id] = Menu(id, name, clbk);
}
void Remove(int id)
{
m_Childrens.erase(id);
}
int GetId() const
{
return m_Id;
}
const std::string & GetName() const
{
return m_Name;
}
const Callback & GetHandler() const
{
return m_Handler;
}
bool IsChildren(int id) const
{
return (m_Childrens.find(id) != m_Childrens.cend());
}
Menu & GetChildren(int id)
{
return m_Childrens.at(id);
}
const SubMenus & GetChildrens() const
{
return m_Childrens;
}
private:
int m_Id;
std::string m_Name;
Callback m_Handler;
SubMenus m_Childrens;
};
void ClearScreen()
{
system("cls");
}
int SharedMenuDisplay(const Menu & menu)
{
ClearScreen();
std::cout << "Welcome to " << menu.GetName() << std::endl;
for (const auto & m : menu.GetChildrens())
{
std::cout << "> " << m.second.GetId() << " - " << m.second.GetName() << std::endl;
}
std::cout << "> 0 - Go Back" << std::endl;
std::cout << "Please select a sub menu: ";
int choice;
std::cin >> choice;
return choice;
}
int Menu_Home(Menu & menu)
{
int choice;
int result = 0;
do {
ClearScreen();
std::cout << "Welcome to " << menu.GetName() << std::endl;
for (const auto & m : menu.GetChildrens())
{
std::cout << "> " << m.second.GetId() << " - " << m.second.GetName() << std::endl;
}
std::cout << "> 0 - To Leave" << std::endl;
std::cout << "Please select a sub menu: ";
std::cin >> choice;
if (choice != 0 && menu.IsChildren(choice))
result = menu.GetChildren(choice).Enter();
} while (choice != 0);
return result;
}
int Menu_A(Menu & menu)
{
int choice;
int result = 0;
do {
choice = SharedMenuDisplay(menu);
if (choice != 0 && menu.IsChildren(choice))
result = menu.GetChildren(choice).Enter();
} while (choice != 0);
return result;
}
int Menu_A_SubMenu_X(Menu & menu)
{
ClearScreen();
std::cout << "You have selected " << menu.GetName() << std::endl;
std::cout << "> Type something and press Enter to go back..." << std::endl;
std::string str;
std::cin >> str;
return 0;
}
int Menu_A_SubMenu_Y(Menu & menu)
{
ClearScreen();
std::cout << "You have selected " << menu.GetName() << std::endl;
std::cout << "> Type something and press Enter to go back..." << std::endl;
std::string str;
std::cin >> str;
return 0;
}
int Menu_A_SubMenu_Z(Menu & menu)
{
ClearScreen();
std::cout << "You have selected " << menu.GetName() << std::endl;
std::cout << "> Type something and press Enter to go back..." << std::endl;
std::string str;
std::cin >> str;
return 0;
}
int Menu_B(Menu & menu)
{
int choice;
int result = 0;
do {
choice = SharedMenuDisplay(menu);
if (choice != 0 && menu.IsChildren(choice))
result = menu.GetChildren(choice).Enter();
} while (choice != 0);
return result;
}
int Menu_B_SubMenu_X(Menu & menu)
{
ClearScreen();
std::cout << "You have selected " << menu.GetName() << std::endl;
std::cout << "> Type something and press Enter to go back..." << std::endl;
std::string str;
std::cin >> str;
return 0;
}
int Menu_B_SubMenu_Y(Menu & menu)
{
ClearScreen();
std::cout << "You have selected " << menu.GetName() << std::endl;
std::cout << "> Type something and press Enter to go back..." << std::endl;
std::string str;
std::cin >> str;
return 0;
}
int Menu_B_SubMenu_Z(Menu & menu)
{
ClearScreen();
std::cout << "You have selected " << menu.GetName() << std::endl;
std::cout << "> Type something and press Enter to go back..." << std::endl;
std::string str;
std::cin >> str;
return 0;
}
int Menu_C(Menu & menu)
{
ClearScreen();
std::cout << "You have selected " << menu.GetName() << std::endl;
std::cout << "> Type something and press Enter to go back..." << std::endl;
std::string str;
std::cin >> str;
return 0;
}
int main(int argc, char **argv)
{
Menu home(-1, "Home", &Menu_Home);
home.Insert(1, "Menu Item A", &Menu_A);
home.Insert(2, "Menu Item B", &Menu_B);
home.Insert(3, "Menu Item C", &Menu_C);
home.GetChildren(1).Insert(1, "Sub Menu Item X", &Menu_A_SubMenu_X);
home.GetChildren(1).Insert(2, "Sub Menu Item Y", &Menu_A_SubMenu_Y);
home.GetChildren(1).Insert(3, "Sub Menu Item Z", &Menu_A_SubMenu_Z);
home[2].Insert(1, "Sub Menu Item X", &Menu_B_SubMenu_X);
home[2].Insert(2, "Sub Menu Item Y", &Menu_B_SubMenu_Y);
home[2].Insert(3, "Sub Menu Item Z", &Menu_B_SubMenu_Z);
return home.Enter();
}

Printing a singly linked list using classes

I am making a program for singly linked lists using multiple files and classes.
I have to have a Node.h, LinkedList.h, Node.cpp, LinkedList.cpp, and a main.cpp
I was having other problems but now my printList() function just prints "List()" instead of "List(node 1, node2, etc...)"
I think my insert might be the problem because my searchNode() doesn't work right either, it always says node not found.
Here is the code I have: (I can't change the Node.h and LinkedList.h files)
Node.h:
//
// Node.h
// Linked Lists
//
#ifndef Linked_Lists_Node_h
#define Linked_Lists_Node_h
class Node
{
public:
Node(int data);
int data;
Node *next;
};
#endif
LinkedList.h:
//
// LinkedList.h
// Linked Lists
//
#ifndef Linked_Lists_LinkedList_h
#define Linked_Lists_LinkedList_h
#include "Node.h"
class LinkedList
{
private:
Node *head;
public:
LinkedList();
void addNode(int data);
void removeNode(int data);
bool searchNode(int data);
void printList();
};
#endif
Node.cpp
//
// Node.cpp
// Linked Lists
//
#include <iostream>
#include <cstdlib>
#include "LinkedList.h"
#include "Node.h"
using namespace std;
Node::Node(int data) {};
LinkedList.cpp
//
// LinkedList.cpp
// Linked Lists
//
#include <iostream>
#include <cstdlib>
#include "LinkedList.h"
#include "Node.h"
using namespace std;
LinkedList::LinkedList()
{
head = NULL;
}
void LinkedList::addNode(int data)
{
Node *newNode;
newNode->data = data;
newNode->next = NULL;
Node *tmp = head;
if(tmp != NULL)
{
while(tmp->next != NULL)
{
tmp = tmp->next;
}
tmp->next = newNode;
}
cout << "Node added" << endl;
printList();
}
void LinkedList::removeNode(int data)
{
Node *tmp = head;
if(tmp == NULL)
{
cout << "No node removed" << endl;
return;
}
if(tmp->next == NULL)
{
delete tmp;
head = NULL;
}
else
{
Node *previous;
do
{
if(tmp->data == data)
{
break;
}
previous = tmp;
tmp = tmp->next;
}
while(tmp != NULL);
previous->next = tmp->next;
delete tmp;
}
cout << "Node removed" << endl;
printList();
}
bool LinkedList::searchNode(int data)
{
Node *tmp = head;
while(tmp != NULL)
{
if(tmp->data == data)
{
cout << "Node found" << endl;
printList();
return true;
}
tmp = tmp->next;
}
cout << "Node not found" << endl;
printList();
return false;
}
void LinkedList::printList()
{
Node *tmp = head;
if(tmp == NULL)
{
cout << "List()" << endl;
return;
}
if(tmp->next == NULL)
{
cout << "List(" << tmp->data << ")";
}
else
{
do
{
cout << "List(" << tmp->data;
cout << ", ";
tmp = tmp->next;
}
while (tmp != NULL);
cout << ")" << endl;
}
}
main.cpp
//
// main.cpp
// Linked Lists
//
#include <iostream>
#include <cstdlib>
#include "LinkedList.h"
#include "Node.h"
#include "LinkedList.cpp"
using namespace std;
int main ()
{
LinkedList list;
int data;
int choice;
while(1)
{
cout << " Select:" << endl;
cout << "1 to add a node" <<endl;
cout << "2 to remove a node" << endl;
cout << "3 to search for a node" << endl;
cout << "4 to exit" << endl;
cout << endl;
cin >> choice;
switch(choice)
{
case 1: //insertion
cout << "Enter node: ";
cin >> data;
list.addNode(data); //add a node
break;
case 2: //deletion
cout << "Enter node: ";
cin >> data;
list.removeNode(data); //remove a node
break;
case 3: //search
cout << "Enter node: ";
cin >> data;
list.searchNode(data); //search for a node
break;
case 4:
exit(0); //exit the program
break;
default: //default case
cout << "Please enter a valid choice (1 - 4)!" << endl;
break;
}
}
return 0;
}
If you could help me figure out my problem I would greatly appreciate it.
You're not adding any nodes. If head is NULL, your add Node becomes:
void LinkedList::addNode(int data)
{
Node *newNode;
newNode->data = data;
newNode->next = NULL;
Node *tmp = head;
if(tmp != NULL)
{
//this never gets executed
}
cout << "Node added" << endl;
printList();
}
You need to treat this case (first insertion):
void LinkedList::addNode(int data)
{
Node *newNode;
newNode->data = data;
newNode->next = NULL;
Node *tmp = head;
if(tmp != NULL)
{
while(tmp->next != NULL)
{
tmp = tmp->next;
}
tmp->next = newNode;
}
else
{
head = newNode;
}
cout << "Node added" << endl;
printList();
}
This will create the head if it doesn't exist already.
Are you using a debugger? It would be much easier (for you) if you did.