How to construct a class with variadic pointer functions as members? - c++

I want to know whether the following is possible in C++. I need to construct a class that will store as a data member a std::map, with keys being of type std::string, and values being function pointers. The thing is that I want these function pointers to be variadic in the sense that they should point to functions accepting an arbitrary number of arguments, i.e. pointing to functions of the form
template<class... Args>
f(Args...);
The important bit is that I want to be able to have different arguments for the different function pointers in the map of a given instance of my class. For example, I might want to create an object of my class and have its map contain two pairs, one corresponding to a function having (double, int) as arguments, and another having (std::vector, int, int) as arguments. And I want to be able to make this general, in the sense that I want to be able to add new elements to the map, with possibly different argument lists (although I would only do this at compile-time, I still need to code the class without knowing about the types since I want to add the new elements from other files/clients).
What is the best way to implement this?

For all those saying you cant, you actually can, it's not pretty:
This is an example code from the output of the moc tool, that does exactly that: It stores an arbitrary amount of function / method pointers, with an arbitrary number of arguments.
Easiest Solution: Just use Qt's moc tool to generate that for you,
If you cannot or don't want to use Qt, you still can analize the code below on how they achieve it.
int AtCore::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 25)
qt_static_metacall(this, _c, _id, _a);
_id -= 25;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 25)
*reinterpret_cast<int*>(_a[0]) = -1;
_id -= 25;
}
return _id;
}
void AtCore::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
AtCore *_t = static_cast<AtCore *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: _t->printProgressChanged((*reinterpret_cast< const float(*)>(_a[1]))); break;
case 1: _t->receivedMessage((*reinterpret_cast< const QByteArray(*)>(_a[1]))); break;
case 2: _t->stateChanged((*reinterpret_cast< PrinterState(*)>(_a[1]))); break;
case 3: _t->print((*reinterpret_cast< const QString(*)>(_a[1]))); break;
case 4: _t->stop(); break;
case 5: _t->pause((*reinterpret_cast< const QString(*)>(_a[1]))); break;
case 6: _t->resume(); break;
case 7: _t->home((*reinterpret_cast< uchar(*)>(_a[1]))); break;
case 8: _t->home(); break;
case 9: _t->setExtruderTemp((*reinterpret_cast< uint(*)>(_a[1])),(*reinterpret_cast< uint(*)>(_a[2]))); break;
case 10: _t->setExtruderTemp((*reinterpret_cast< uint(*)>(_a[1]))); break;
case 11: _t->setExtruderTemp(); break;
case 12: _t->move((*reinterpret_cast< uchar(*)>(_a[1])),(*reinterpret_cast< uint(*)>(_a[2]))); break;
case 13: _t->setBedTemp((*reinterpret_cast< uint(*)>(_a[1]))); break;
case 14: _t->setBedTemp(); break;
case 15: _t->setFanSpeed((*reinterpret_cast< uint(*)>(_a[1])),(*reinterpret_cast< uint(*)>(_a[2]))); break;
case 16: _t->setFanSpeed((*reinterpret_cast< uint(*)>(_a[1]))); break;
case 17: _t->setFanSpeed(); break;
case 18: _t->setAbsolutePosition(); break;
case 19: _t->setRelativePosition(); break;
case 20: _t->setPrinterSpeed((*reinterpret_cast< uint(*)>(_a[1]))); break;
case 21: _t->setPrinterSpeed(); break;
case 22: _t->setFlowRate((*reinterpret_cast< uint(*)>(_a[1]))); break;
case 23: _t->setFlowRate(); break;
case 24: _t->close(); break;
default: ;
}
} else if (_c == QMetaObject::IndexOfMethod) {
int *result = reinterpret_cast<int *>(_a[0]);
void **func = reinterpret_cast<void **>(_a[1]);
{
typedef void (AtCore::*_t)(const float & );
if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&AtCore::printProgressChanged)) {
*result = 0;
return;
}
}
{
typedef void (AtCore::*_t)(const QByteArray & );
if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&AtCore::receivedMessage)) {
*result = 1;
return;
}
}
{
typedef void (AtCore::*_t)(PrinterState );
if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&AtCore::stateChanged)) {
*result = 2;
return;
}
}
}
}

Related

How to build the simple change maker for a vending machine?

On the menu deposits n,d, q, o,f are indicated which are indication for nickel dime quarter , one dollar and five dollar. I should also indicate "C" as in cancel option when the user hits c. But i couldn't make it work. My program still runs even the user hit c. I am confused on this point?
switch(DepositIndication) {
case 'n': {
PurchasedPrice=PurchasedPrice-0.05;
NumOfNickels=NumOfNickels+1;
}
break;
case 'd': {
PurchasedPrice=PurchasedPrice-0.10;
NumOfdimes=NumOfdimes+1;
}
break;
case 'q': {
PurchasedPrice=PurchasedPrice-0.25;
NumOfquarters=NumOfquarters+1;
}
break;
case 'o': {
PurchasedPrice=PurchasedPrice-1.00;
NumOfOnes=NumOfOnes+1;
}
break;
case 'f': {
PurchasedPrice=PurchasedPrice-5.00;
NumOfFives=NumOfFives+1;
}
break;
}
the condition c is missing and I Put the break into to brackets;
switch (DepositIndication) {
case 'n':
{
PurchasedPrice = PurchasedPrice - 0.05;
NumOfNickels = NumOfNickels + 1;
break;
}
case 'd':
{
PurchasedPrice = PurchasedPrice - 0.10;
NumOfdimes = NumOfdimes + 1;
break;
}
case 'q':
{
PurchasedPrice = PurchasedPrice - 0.25;
NumOfquarters = NumOfquarters + 1;
break;
}
case 'o':
{
PurchasedPrice = PurchasedPrice - 1.00;
NumOfOnes = NumOfOnes + 1;
break;
}
case 'f':
{
PurchasedPrice = PurchasedPrice - 5.00;
NumOfFives = NumOfFives + 1;
break;
}
case 'c':
}
//you can print cancellation messages in here
break;
}
default:
break;
}
I should also indicate "C" as in cancel option when the user hits c
Your current code works fine the only thing you are missing to make that work right now is a default case or a case where you specifically check if the user inputed C.
Example:
switch(DepositIndication) {
// All other cases ...
case 'c': {
// The user canceled the interaction
std::cout << "Interaction was canceled." << std::endl;
break;
}
// Default case to ensure that even,
// if the user hits any other key we still handle his interaction
default {
std::cout << "No fitting interactional behaviour found." << std::endl;
break;
}
}
If you want to ensure that the user can even input big lettered chars and the switch case will still work you can use std::tolower and cast it back to a char.
Make the User-Input lowercase:
// Make DepositIndication lowercase
DepositIndication = std::tolower(DepositIndication, std::locale());

Helps with TGrid

I'm a newbie in C++ Builder and really need some help. In my work, we have to use C++ Builder and I can't find very much documentation about it.
What I want to do is to insert a new row with some data in each column each time the user press the Insert key. There are 20 rows in total in my TGrid: 1 TCheckColumn and 19 TStringColumn.
I don't know how to do it exactly. First, here is the code I already wrote when someone enter the insert key:
void __fastcall TForm2::Grid1KeyDown(TObject *Sender, WORD &Key, System::WideChar &KeyChar,
TShiftState Shift)
{
switch(Key)
{
case VK_INSERT:
if(Grid1->RowCount>MAXTask){}else
{
Label1->Text = "number Task: "+IntToStr(++nmbertask);
Grid1->RowCount++;
}
break;
}
}
Here is the Grid1GetValue() and Grid1SetValue() code:
void __fastcall TForm2::Grid1GetValue(TObject *Sender, const int Col, const int Row,
TValue &Value)
{
switch(Col)
{
case 0:
Value = A[Col][Row]; break;
case 1:
Value = A[Col][Row]; break;
case 2:
Value = A[Col][Row]; break;
case 3:
Value = A[Col][Row]; break;
case 4:
Value = A[Col][Row]; break;
case 5:
Value = A[Col][Row]; break;
case 6:
Value = A[Col][Row]; break;
case 7:
Value = A[Col][Row]; break;
case 8:
Value = A[Col][Row]; break;
case 9:
Value = A[Col][Row];break;
case 10:
Value = A[Col][Row];break;
case 11:
Value = A[Col][Row];break;
case 12:
Value = A[Col][Row];break;
case 13:
Value = A[Col][Row];break;
case 14:
Value = A[Col][Row];break;
case 15:
Value = A[Col][Row];break;
case 16:
Value = A[Col][Row];break;
case 17:
Value = A[Col][Row];break;
case 18:
Value = A[Col][Row]; break;
case 19:
Value = A[Col][Row];break;
}
}
void __fastcall TForm2::Grid1SetValue(TObject *Sender, const int Col, const int Row,
const TValue &Value)
{
switch(Col)
{
case 0:
A[Col][Row] = Value; break;
case 1:
A[Col][Row] = Value; break;
case 2:
A[Col][Row] = Value; break;
case 3:
A[Col][Row] = Value; break;
case 4:
A[Col][Row] = Value; break;
case 5:
A[Col][Row] = Value; break;
case 6:
A[Col][Row] = Value; break;
case 7:
A[Col][Row] = Value; break;
case 8:
A[Col][Row] = Value; break;
case 9:
A[Col][Row] = Value; break;
case 10:
A[Col][Row] = Value; break;
case 11:
A[Col][Row] = Value; break;
case 12:
A[Col][Row] = Value; break;
case 13:
A[Col][Row] = Value; break;
case 14:
A[Col][Row] = Value; break;
case 15:
A[Col][Row] = Value; break;
case 16:
A[Col][Row] = Value; break;
case 17:
A[Col][Row] = Value; break;
case 18:
A[Col][Row] = Value; break;
case 19:
A[Col][Row] = Value; break;
}
}
This is what I've done so far. I've never developed in C++ Builder, so can you help me please? I'm not really looking for a written solution, I'm really looking for an indication of where to look for a solution.
If I'm not clear, please indicate it so I can give more information. If you also have a good site with good documentation about C++ Builder, please indicate it to me. English is not my native language but I will do my best.
You can find the TGrid documentation on Embarcadero's DocWiki. Look at the 'Methods' page to figure out how to insert and remove elements in your TGrid. There are two methods that can help you: InsertComponent() and `InsertObject().
Also, in your Grid1GetValue() and Grid1SetValue() methods, you are using a switch statement. In all those cases you are doing the same job :
Value = A[Col][Row];break;
So, instead of using a switch, you can simply call one time Value = A[Col][Row]; and it will do the same result.
I hope my answer can help you. At least I answered what I understood from your question.

How do i sort strings into linked lists according to their initials?

Hello everyone so this is my first question here.I will try to explain my problem as briefly as i can.So i am trying to sort a taken string into 26 different lists according to their initials.I don't know if this is a proper approach since i am only a student yet.When i run this code i get the following error which i could not find any solution for.
error C4700: uninitialized local variable 'item' used
Here is my node struct and my linked list is just as any other linked list class.
template
struct nodeType
{
int wCount;
Type info;
nodeType<Type> *link;
};
So my question is why do i get this error and is there any better approach for my problem.(By the way this is just a part of what i am trying to do normally i should be reading a processed text file and inserting every word into a list according to their initials and increase their count if they exist in the list.)
#include <iostream>
#include "unorderedLinkedListType.h"
#include <string>
using namespace std;
int main()
{
unorderedLinkedList<string> listA, listB, listC, listD, listE, listF, listG,
listH, listI, listJ, listK, listL, listM, listN, listO, listP, listQ, listR,
listS, listT, listU, listV, listW, listX, listY, listZ;
nodeType<string> *item; // Node Definition
item->info = "trying";
item->link = NULL;
item->wCount = 0;
char first; // Taking the initial of a string
first = item->info[0];
switch (first) // Switch case for insertion to lists
{
case 'a': if (listA.search(item->info)){ item->wCount++; }
else { listA.insertFirst(item->info); }
break;
case 'b': if (listB.search(item->info)){ item->wCount++; }
else { listB.insertFirst(item->info); }
break;
case 'c': if (listC.search(item->info)){ item->wCount++; }
else { listC.insertFirst(item->info); }
break;
case 'd': if (listD.search(item->info)){ item->wCount++; }
else { listD.insertFirst(item->info); }
break;
case 'e': if (listE.search(item->info)){ item->wCount++; }
else { listE.insertFirst(item->info); }
break;
case 'f': if (listF.search(item->info)){ item->wCount++; }
else { listF.insertFirst(item->info); }
break;
case 'g': if (listG.search(item->info)){ item->wCount++; }
else { listG.insertFirst(item->info); }
break;
case 'h': if (listH.search(item->info)){ item->wCount++; }
else { listH.insertFirst(item->info); }
break;
case 'i': if (listI.search(item->info)){ item->wCount++; }
else { listI.insertFirst(item->info); }
break;
case 'j': if (listJ.search(item->info)){ item->wCount++; }
else { listJ.insertFirst(item->info); }
break;
case 'k': if (listK.search(item->info)){ item->wCount++; }
else { listK.insertFirst(item->info); }
break;
case 'l': if (listL.search(item->info)){ item->wCount++; }
else { listL.insertFirst(item->info); }
break;
case 'm': if (listM.search(item->info)){ item->wCount++; }
else { listM.insertFirst(item->info); }
break;
case 'n': if (listN.search(item->info)){ item->wCount++; }
else { listN.insertFirst(item->info); }
break;
case 'o': if (listO.search(item->info)){ item->wCount++; }
else { listO.insertFirst(item->info); }
break;
case 'p': if (listP.search(item->info)){ item->wCount++; }
else { listP.insertFirst(item->info); }
break;
case 'q': if (listQ.search(item->info)){ item->wCount++; }
else { listQ.insertFirst(item->info); }
break;
case 'r': if (listR.search(item->info)){ item->wCount++; }
else { listR.insertFirst(item->info); }
break;
case 's': if (listS.search(item->info)){ item->wCount++; }
else { listS.insertFirst(item->info); }
break;
case 't': if (listT.search(item->info)){ item->wCount++; }
else { listT.insertFirst(item->info); }
break;
case 'u': if (listU.search(item->info)){ item->wCount++; }
else { listU.insertFirst(item->info); }
break;
case 'v': if (listV.search(item->info)){ item->wCount++; }
else { listV.insertFirst(item->info); }
break;
case 'w': if (listW.search(item->info)){ item->wCount++; }
else { listW.insertFirst(item->info); }
break;
case 'x': if (listX.search(item->info)){ item->wCount++; }
else { listX.insertFirst(item->info); }
break;
case 'y': if (listY.search(item->info)){ item->wCount++; }
else { listY.insertFirst(item->info); }
break;
case 'z': if (listZ.search(item->info)){ item->wCount++; }
else { listZ.insertFirst(item->info); }
break;
}
listT.print(); // Printing the listT to try out my code
return 0;
}
nodeType<string> *item; is a pointer to an item. But you never allocated the item and initialized the pointer. Please use a std::map instead of this creepy switch statement and 26 lists.
#include <map>
int main()
{
std::map< char, unorderedLinkedList<string> > listMap;
nodeType<string> *item = new nodeType<string>();
item->info = "trying";
item->link = NULL;
item->wCount = 0;
char first;
first = item->info[0];
if (listMap[first].search(item->info))
{
item->wCount++;
}
else
{
listMap[first].insertFirst(item->info);
}
// ...
}

How to apply different instantiations to the same name of object?

int lim;
do{
cin>>lim;
switch(lim)
{
case 1: {mpa<1,int,const char*> C; }break;
case 2: {mpa<2,int,const char*> C; }break;
case 3: {mpa<3,int,const char*> C; }break;
case 4: {mpa<4,int,const char*> C; }break;
case 5: {mpa<5,int,const char*> C; }break;
default: cout<<"Incorrect number, please repeat\n";
}
}while(lim<1 || lim>5);
I want to pass a value(1,2,3,4 or 5) to the template int a,typename T1,typename T2. I need different instantiations of this template. But object C will be destroyed after switch. How to apply different instantiations to the same name of object?
In this case, I think the best option is to rethink class mpa to not require that first parameter at compile time. Seriously, everyone hates rewriting things, but that's what you should do.
Since I know you'll ignore that, here's a workaround:
Make a class mpa_base<class, class>, that mpa inherits from, and has all the same functions, but they're all virtual (ESPECIALLY the destructor). Then, you can do this:
typedef mpa_base<int, const char*> mpa_int_pchar;
std::unique_ptr<mpa_int_pchar> C; //this is a smart pointer to a mpa object
int lim;
do{
cin>>lim;
switch(lim)
{
case 1: C.reset(new mpa<1,int,const char*>()); break;
case 2: C.reset(new mpa<2,int,const char*>()); break;
case 3: C.reset(new mpa<3,int,const char*>()); break;
case 4: C.reset(new mpa<4,int,const char*>()); break;
case 5: C.reset(new mpa<5,int,const char*>()); break;
default: cout<<"Incorrect number, please repeat\n";
}
}while(lim<1 || lim>5);
Refactor the common part in another function and then you can easily do this. Also, always have the input from the stream as part of the loop check or make it a break-condition.
template<class MPA>
void foo(MPA const& mpa){
// whatever you want to do, do it here
}
int lim = 0;
do{
if(!(cin >> lim)){ // broken input
cin.clear(); // clear error flags
break; // bail out
}
switch(lim)
{
case 1: { foo(mpa<1, int, char const*>(/*params*/)); }break;
case 2: { foo(mpa<2, int, char const*>(/*params*/)); }break;
case 3: { foo(mpa<3, int, char const*>(/*params*/)); }break;
case 4: { foo(mpa<4, int, char const*>(/*params*/)); }break;
case 5: { foo(mpa<5, int, char const*>(/*params*/)); }break;
default: cout<<"Incorrect number, please repeat\n";
}
}while(lim < 1 || lim > 5);

I wanted to know how to properly use switch/case

I was just wondering if someone could just give me an example of how to use switch/case. I kinda get the just of it but am having trouble figuring out what and how i can use this. Thank you in advance.
There are couple of things to remember about switch case statements:
a) The condition should be integeral/enum/user defined type which supports conversion to int or enum
b) case lables are compile time constants
c) No two case label expressions can have the same value
d) $6.4.2/5- "When the switch statement is executed, its condition is evaluated and compared with each case constant. If one of the case constants is equal to the value of the condition, control is passed to the statement following the matched case label. If no case constant matches the condition, and if there is a default label,control passes to the statement labeled by the default label. If no case matches and if there is no default then none of the statements in the switch is executed."
e) $6.4.2/6- "case and default labels in themselves do not alter the flow of control, which continues unimpeded across such labels. To exit from a switch, see break"
enum direction {north, south, east, west};
char x;
class UD{
operator int(){return 0;}
};
direction f1(){
return north;
}
char f2(){
return 'A';
}
int main(){
direction d = f();
string country;
// switch condition of type enum
switch(d){
case north:
country = "P";
break;
case south:
country = "Q";
break;
case east:
country = "R";
break;
case west:
country = "S";
break;
default:
country = "";
break;
}
// switch condition of integral type
switch(c){
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
cout << "Vowel";
break;
default:
cout << "Not a Vowel";
break;
}
UD u;
// switch condition of user defined type (conversion to integral type)
switch(u){
case 0:
case 1:
cout << "Good";
break;
default:
cout << "Not so good";
break;
}
}
Here is a fairly typical use case. You have a list of values (the enum) and a switch which checks the input to determine which you are dealing with. This assumes of course that the action you will take depends on the underlying value of the enum.
enum ImageFormat
{
FormatRGB888,
FormatRGB8888,
FormatRGB101010,
FormatRGB161616,
FormatRGB16161616
};
void SomeFunc(ImageFormat format)
{
switch(format)
{
case FormatRGB888:
// do stuff
break;
case FormatRGB8888:
// do stuff
break;
case FormatRGB101010,
// do stuff
break;
case FormatRGB161616:
// do stuff
break;
case FormatRGB16161616:
// do stuff
break;
default:
// bad value for 'format'
}
}
Say you have an enum
enum expr_type {
EXPR_TYPE_ADD,
EXPR_TYPE_SUBTRACT,
EXPR_TYPE_GET_VALUE
};
We can do a switch on this:
enum expr_type t = /* get input somehow and find the type */;
switch(t) {
case EXPR_TYPE_ADD:
cout << "Operator Add";
/* fall through */
case EXPR_TYPE_SUBTRACT:
cout << "Operator (Add or Subtract)";
break;
case EXPR_TYPE_GET_VALUE;
cout << "Getting some value";
break;
}
You have to put in the break; so it doesn't fallthrough - Currently, EXPR_TYPE_ADD will exute all the code for EXPR_TYPE_SUBTRACT. Make sure to use break correctly!
Switch statements are a more efficient way of doing a lot of ifs and elses.
import java.util.Scanner;
class Date{
public static void main(String[] args) {
String dow;
String wowby;
String yowby;
Double n1,n2,res;
Scanner scan = new Scanner (System.in);
System.out.print("Enter Date (dd/mm/yy): ");
String date = scan.nextLine();
String dd = date.substring(0,2);
String mm = date.substring(3,5);
String yy = date.substring(6,8);
int d = Integer.valueOf(dd);
int m = Integer.valueOf(mm);
int y = Integer.valueOf(yy);
boolean valid = (d>=1) && (d<31)||(m>=1) && (m<12);//||((y>=00) && (y<99));
if(!valid)
System.out.print("Invalid date");
else {
switch (dd)
{
case "01":
System.out.print("First of ");
switch (mm) {
case "01":
System.out.print("January,2020");
break;
case "02":
System.out.print("February,2020");
break;
case "03":
System.out.print("March,2020");
break;
case "04":
System.out.print("April,2020");
break;
case "05":
System.out.print("May,2020");
break;
case "06":
System.out.print("June,2020");
break;
case "07":
System.out.print("July,2020");
break;
case "08":
System.out.print("August,2020");
break;
case "09":
System.out.print("September,2020");
break;
case "10":
System.out.print("October,2020");
break;
case "11":
System.out.print("November,2020");
break;
case "12":
System.out.print("December,2020");
break;
default:
System.out.print(" Invalid date ");
}
break;
case "02":
System.out.print("Second of ");
switch (mm)
{
case "01":
System.out.print("January,2020");
break;
case "02":
System.out.print("February,2020");
break;
case "03":
System.out.print("March,2020");
break;
case "04":
System.out.print("April,2020");
break;
case "05":
System.out.print("May,2020");
break;
case "06":
System.out.print("June,2020");
break;
case "07":
System.out.print("July,2020");
break;
case "08":
System.out.print("August,2020");
break;
case "09":
System.out.print("September,2020");
break;
case "10":
System.out.print("October,2020");
break;
case "11":
System.out.print("November,2020");
break;
case "12":
System.out.print("December,2020");
break;
default:
System.out.print(" Invalid month ");
}
break;
case "03":
System.out.print("Third of ");
switch (mm)
{
case "01":
System.out.print("January,2020");
break;
case "02":
System.out.print("February,2020");
break;
case "03":
System.out.print("March,2020");
break;
case "04":
System.out.print("April,2020");
break;
case "05":
System.out.print("May,2020");
break;
case "06":
System.out.print("June,2020");
break;
case "07":
System.out.print("July,2020");
break;
case "08":
System.out.print("August,2020");
break;
case "09":
System.out.print("September,2020");
break;
case "10":
System.out.print("October,2020");
break;
case "11":
System.out.print("November,2020");
break;
case "12":
System.out.print("December,2020");
break;
default:
System.out.print(" Invalid month ");
}
return;
}
}
}
}