c++ pushing dereferenced objects to vector - c++

I'm making a function to take in a reference to a path on the filesystem and recursively add file names to a vector. But first I have to be able to add paths to a vector.
what is wrong with this method?
namespace filesys = boost::filesystem;
Method:
void recursive_file_list(filesys::path & root_path, vector<filesys::path> & paths) {
paths->push_back(*root_path); // line 14
// TODO: add more logic to actually recurse through file system
// for now just add root_path (even though root_path is path of directory, not file)
}
And I call it like so:
int main(int argc, char* argv[]) {
// Use the command line arguments
filesys::path abs_path; // line 23
if ( argc > 1 )
// Make the system complete this path to absolute path
abs_path = filesys::system_complete( filesys::path( argv[1] ) );
else {
// If no arguments given
cout << "usage: list_files [path]" << endl;
exit(1);
}
// Is this a valid path?
if (!filesys::exists( abs_path )) {
cout << "The path you have specified does not exist." << endl;
exit(2);
}
// If this is a directory
vector<filesys::path> filepaths();
if (filesys::is_directory( abs_path )) {
cout << "You have specified a directory." << endl;
recursive_file_list(&abs_path, &filepaths);
}
else {
cout << "You have specified a file." << endl;
}
}
Error:
list_files.cpp: In function 'void recursive_file_list(boost::filesystem3::path&, std::vector<boost::filesystem3::path, std::allocator<boost::filesystem3::path> >&)':
list_files.cpp:14: error: base operand of '->' has non-pointer type 'std::vector<boost::filesystem3::path, std::allocator<boost::filesystem3::path> >'
list_files.cpp:14: error: no match for 'operator*' in '*root_path'
list_files.cpp: In function 'int main(int, char**)':
list_files.cpp:43: error: invalid initialization of non-const reference of type 'boost::filesystem3::path&' from a temporary of type 'boost::filesystem3::path*'
list_files.cpp:13: error: in passing argument 1 of 'void recursive_file_list(boost::filesystem3::path&, std::vector<boost::filesystem3::path, std::allocator<boost::filesystem3::path> >&)'
I don't understand - I'm passing it by reference and then dereferencing it to add it...not sure what I'm doing wrong.

You can't dereference references! The * and -> operators do not apply to references; you would push the path itself to the vector itself:
paths.push_back(root_path); // line 14
and furthermore, you don't pass addresses to reference arguments, just the arguments themselves, so you would call the function like this:
recursive_file_list(abs_path, filepaths);
References have pointer-like non-copy semantics all by themselves; you do not need to help them along by taking addresses or trying to dereference them.

Related

C++ : how to change a member function at runtime (inside a shared library)?

I have a class DoorTerminal with a member function getInput() as shown below.
DoorTerminal::DoorTerminal(DialogueBox *dialogue_, Door* door_): DialogueInterfacing(dialogue_){
emptyFor.push_back(string("Player"));
type.push_back(string("DoorTerminal"));
type.push_back(string("DialogueInterfacing"));
imgpath = "/vagrant_data/Skeleton-game/src/sprites/terminal.png";
typestring = "DoorTerminal";
door = door_;
}
void DoorTerminal::getInput(){
string input = dialogue->getInput();
if(input == "1234"){
door->unlock();
}
}
I'm trying to create an instance of this class inside a function defined in a .so shared library and change the getInput function pointer to instead point to a different function at runtime, like so
void getInput2(){
string input = "EE";
if(input == "1234"){
cout << "hello" << endl;
}
}
DoorTerminal* doorTerminal = new DoorTerminal(Door* door);
doorTerminal->getInput = getInput2;
which results in an "invalid use of member function" error.
I've also experimented with std::function for the same purpose but so far with no luck.
Is there a simple way to do this?

Error in Using Root/C++: No matching constructor for initialization of 'TTree'

I am trying to plot the invariant mass of the Z boson from two decayed muons. I am using MadGraph and Root. MadGraph simulates the events (p p > Z > mu+ and mu-) and creates a .root file that contains the events. I called the simulation eventgeneration.
To use Root to analyze the data and draw the histogram, I have to write my code in C++. Here is the code:
#ifdef __CLING__
R__LOAD_LIBRARY(libDelphes)
#include "TFile.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TH1F.h"
#include <iostream>
#include "classes/DelphesClasses.h"
#include "external/ExRootAnalysis/ExRootTreeReader.h"
#include "external/ExRootAnalysis/ExRootResult.h"
#else
class ExRootTreeReader;
class ExRootResult;
using namespace std;
#endif
void readEvents(const char *inputFile)
{
gSystem->Load("libDelphes");
TChain chain("Delphes");
chain.Add(inputFile);
ExRootTreeReader *treeReader = new ExRootTreeReader(&chain);
Long64_t numberOfEntries = treeReader->GetEntries();
TTree *tree = new TTree(&chain);
TClonesArray *branchMuon = treeReader->UseBranch("Muon");
//Long64_t numberOfMuons = branchMuon->GetEntries();
TClonesArray *branchElectron = treeReader->UseBranch("Electron");
Long64_t numberOfElectrons = branchElectron->GetEntries();
cout << "There are " << numberOfEntries << " entries in your ntuple" << endl;
UInt_t Muons;
Float_t MuonEta1;
Float_t MuonPhi1;
Float_t MuonPt1;
Float_t MuonEta2;
Float_t MuonPhi2;
Float_t MuonPt2;
tree->SetBranchAddress("MuonEta1", &MuonEta1);
tree->SetBranchAddress("MuonPhi1", &MuonPhi1);
tree->SetBranchAddress("MuonPt1", &MuonPt1);
tree->SetBranchAddress("MuonEta2", &MuonEta2);
tree->SetBranchAddress("MuonPhi2", &MuonPhi2);
tree->SetBranchAddress("MuonPt2", &MuonPt2);
TH1F *histDiMuonMass = new TH1F("mass", "M_{inv}(mu+[1], mu-[2]); M_inv (GeV/c^2); Events", 50, 0.0, 1500);
for(Int_t entry = 0; entry < numberOfEntries; ++entry)
{
treeReader->ReadEntry(entry);
Long64_t numberOfMuons = branchMuon->GetEntries();
//Muons += entry;
//Muon *muon1, *muon2, *muon3, *muon4;
TLorentzVector muon1;
TLorentzVector muon2;
muon1.SetPtEtaPhiM(MuonPt1, MuonEta1, MuonPhi1, 0.1);
muon2.SetPtEtaPhi(MuonPt2, MuonEta2, MuonPhi2, 0.1);
if(branchMuon->GetEntries() == 4)
{
TLorentzVector Z = muon1 + muon2;
histDiMuonMass->Fill(Z.M());
}
}
cout << "There are " << Muons << " entries in your ntuple" << endl;
histDiMuonMass->Draw();
}
Then in the root terminal I type: \
.x examples/readEvents.C("../eventgeneration/Events/run_01/tag_1_delphes_events.root")
However, I get the following error:
In file included from input_line_1563:1:
/mnt/c/1/MG5_aMC_v2_6_6/Delphes/examples/readEvents.C:30:20: error: no matching constructor for initialization of 'TTree'
TTree *tree = new TTree(&chain);
^ ~~~~~~
/home/cucip/builddir/include/TTree.h:295:4: note: candidate constructor not viable: no known conversion from 'TChain *' to 'const TTree' for 1st argument; remove &
TTree(const TTree& tt) = delete;
^
/home/cucip/builddir/include/TTree.h:291:4: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
TTree();
^
/home/cucip/builddir/include/TTree.h:292:4: note: candidate constructor not viable: requires at least 2 arguments, but 1 was provided
TTree(const char* name, const char* title, Int_t splitlevel = 99, TDirectory* dir = gDirectory);
^
In file included from input_line_1563:1:
/mnt/c/1/MG5_aMC_v2_6_6/Delphes/examples/readEvents.C:72:8: error: no member named 'SetPtEtaPhi' in 'TLorentzVector'
muon2.SetPtEtaPhi(MuonPt2, MuonEta2, MuonPhi2, 0.1);
Does anybody see what could cause this error and how I can fix it?
Many thanks!
By calling new TTree(&chain) you're trying to call a constructor for a TTree and you provide it with a TChain * (the type of chain is TChain, so &chain is a pointer to a TChain).
The constructors for TTree https://root.cern/doc/v618/classTTree.html take either no argument or two const char* (usually string literals or .Data() of a TString or .c_str() of a std::string or the output of ROOT's Form …).
It looks like you try to call the deleted constructor TTree(const TTree&tt)=delete, which doesn't work for several reasons:
you're providing a pointer to a TTree instead of a TTree by reference (not even sure from the top of my head if casting from TChain to TTree would work if the & wasn't there.
the constructor is deleted, so it doesn't actually exist and cannot be called.
However, from the looks of it, you want to use your TChain as a TTree*, which doesn't require any code from your side to begin with because a TChain already is a TTree by inheritance. So, you can use chain. instead of tree->, or (if having a pointer variable is really more desirable for reasons that I don't see in the example) create a TTree* (i.e. create only the pointer to a TTree, instead of creating the actual TTree on the heap and get a pointer to it from the new operator) by doing something like
TTree* tree = &chain;

My program is rebelling? Changes are not made

I have an annoying problem with Visual Studio. Indeed, I am in the design of a compiler, and I have a file reserved for error messages. It works with a dictionary (std::map): code → message.
However, the changes made to the dictionary do not seem to affect the program, which reacts as if no changes had been made.
It would be difficult for me to explain more clearly with words, so I recorded a video. (It does not belong to the site, sorry, I did not find how to include it i, this post).
As you can see, we use a function that displays the error message as it gets it from the dictionary :
std::map<ErrorCodes, std::string> Messages;
...
std::string ErrMessage = Messages[code];
I do not understand why the changes made do not affect the program as intended. It seems that Visual Studio no longer compiles part of the code...
Indeed, in the recording, we can see that the error message displayed in the console is the [E29] (the old one before the [E80]), and that the message displayed is not the one that corresponds with the enumeration either.
The problem may seem simple, but I honestly do not see where it might lie...
EDIT:
Here is a more detailed explanation:
In the video, the program running in the console is mine. "Compilation not success" is my own error message, and it is normal that it is displayed.
Here is the call code of the error call display:
exception.ThrowError(exception.E0080);
E0080 is the error listing code, here are the error message files :
*.hpp:
class Exception {
public:
enum ErrorCodes {
E0000,
E0001, // Can't load file
E0002, // Can't find header file
E0003, // Expected file name
E0004, // Unexpected token
E0005, // Expected Identifier
E0006, // Value without storage object
E0007, // Already existing object
E0008, // Redefined preprocessor definition
E0009, // Redefined variable
E0010, // Redefined function
E0011, // Redefined object
E0012, // Redefined rule
E0013, // Redefined value
E0014, // Undefined identifier
E0015, // Buoyage symbol missing
E0016, // Expected end of line symbol (';')
E0017, // Unexpected character
E0018, // Unknown token
E0019, // Non-close comment
E0020, // Non-compliant typing
E0021, // Use of uninitialized data
E0022, // Unacceptable suffix
E0023, // Invalid keyword combination
E0024, // Declaration not in accordance with non-local use
E0025, // Incompatible value with type / object defined
E0026, // Constant value too wide
E0027, // Too much initialization value in a static size array
E0028, // Non-conforming identifier
E0029, // Expected statement
E0030, // Wrong identifier format (the expected format is ASCII)
E0031, // Wrong pointer initialization
E0032, // Non-valid literal suffix
E0033, // No object can have the identifier 'vanaur'
E0034, // Non-existent object field
E0035, // Non-existent object method
E0036, // Missing function call arguments
E0037, // A rvalue cannot be accessed via the pointers
E0038, // The use of a pointer is unacceptable in this context
E0039, // A reference cannot be made to a constant value
E0040, // Invalid assembler code in external expression
E0041, // The types of the two objects do not match in the image assignment
E0042, // Only a defined object can be destroyed by the delete operator
E0043, // Empty template
E0044, // Object not existing in this namespace
E0045, // Typage temptation with a non-instanciated structure
E0046, // Temptation to access a private field of the object
E0047, // Temptation to access a private method of the object
E0048, // Invalid operator
E0049, // Reserved identifier
E0050, // Wrong usage of postfix and prefix operator
E0051, // Temptation to access an inaccessible element in a table
E0052, // The main function can only have 3 arguments variation
E0053, // This function is not defined as being able to return an array
E0054, // A non-instanciated structure cannot be used as an object instance with the keyword 'new'.
E0055, // Wrong choice of the anonymous string concatenation operator (between '^' and'+')
E0056, // An object can only inherit from one other object
E0057, // Incorrect 'typename' value
E0058, // Incorrect 'typesize' value
E0059, // The identifier of a process ('proc') cannot contain spaces
E0060, // The identifier of a process ('proc') cannot contain balises
E0061, // An exception cannot be thrown out of a function
E0062, // Syntax error
E0063, // The increment value of an iteration (with step) must be numerical
E0064, // An anonymous array serving as an iterator to a for loop cannot be empty
E0065, // Wrong ternary condition format
E0066, // A 'ret' instruction must only fit on one instruction (one line = one ';')
E0067, // Division by zero
E0068, // Wrong enumeration value
E0069, // 'Upon' block members cannot contain expressions other than 'it'
E0070, // A match/case expression must contain at least one 'case' expression before using 'default'
E0071, // Unknown error
E0072, // Undefined object
E0073, // Not a valid math expression
E0074, // Expected character
E0075, // Unbalanced brackets
E0076, // Non-ascii character detected
E0077, // The current version of Arlia only accepts constant values as optional function parameters
E0078, // Undefined type
E0079, // Statement not recognised in this context
E0080, // Invalid statement
};
void ThrowError(ErrorCodes, char);
void ThrowError(ErrorCodes, std::string);
void ThrowError(ErrorCodes, token_t);
void ThrowError(ErrorCodes, token_t, Expr);
void ThrowError(ErrorCodes, Expr);
private:
std::map<ErrorCodes, std::string> Messages =
{
{ E0001, " Can't load file" },
{ E0002, " Can't find header file" },
{ E0003, " Expected file name" },
{ E0004, " Unexpected token" },
{ E0005, " Expected Identifier" },
{ E0006, " Value without storage object" },
{ E0007, " Already existing object" },
{ E0008, " Redefined preprocessor definition" },
{ E0009, " Redefined variable" },
{ E0010, " Redefined function" },
{ E0011, " Redefined object" },
{ E0012, " Redefined rule" },
{ E0013, " Redefined value" },
{ E0014, " Undefined identifier" },
{ E0015, " Buoyage symbol missing" },
{ E0016, " Expected end of line symbol (';')" },
{ E0017, " Unexpected character" },
{ E0018, " Unknown token" },
{ E0019, " Non-close comment" },
{ E0020, " Non-compliant typing" },
{ E0021, " Use of uninitialized data" },
{ E0022, " Unacceptable suffix" },
{ E0023, " Invalid keyword combination" },
{ E0024, " Declaration not in accordance with non-local use" },
{ E0025, " Incompatible value with type / object defined" },
{ E0026, " Constant value too wide" },
{ E0027, " Too much initialization value in a static size array" },
{ E0028, " Non-conforming identifier" },
{ E0029, " Expected statement" },
{ E0030, " Wrong identifier format (the expected format is ASCII)" },
{ E0031, " Wrong pointer initialization" },
{ E0032, " Non-valid literal suffix" },
{ E0033, " No object can have the identifier 'vanaur'" },
{ E0034, " Non-existent object field" },
{ E0035, " Non-existent object method" },
{ E0036, " Missing function call arguments" },
{ E0037, " A rvalue cannot be accessed via the pointers" },
{ E0038, " The use of a pointer is unacceptable in this context" },
{ E0039, " A reference cannot be made to a constant value" },
{ E0040, " Invalid assembler code in external expression" },
{ E0041, " The types of the two objects do not match in the image assignment" },
{ E0042, " Only a defined object can be destroyed by the delete operator" },
{ E0043, " Empty template" },
{ E0044, " Object not existing in this namespace" },
{ E0045, " Typage temptation with a non-instanciated structure" },
{ E0046, " Temptation to access a private field of the object" },
{ E0047, " Temptation to access a private method of the object" },
{ E0048, " Invalid operator" },
{ E0049, " Reserved identifier" },
{ E0050, " Wrong usage of postfix and prefix operator" },
{ E0051, " Temptation to access an inaccessible element in a table" },
{ E0052, " The main function can only have 3 arguments variation" },
{ E0053, " This function is not defined as being able to return an array" },
{ E0054, " A non-instanciated structure cannot be used as an object instance with the keyword 'new'" },
{ E0055, " Wrong choice of the anonymous string concatenation operator (between '^' and'+')" },
{ E0056, " An object can only inherit from one other object" },
{ E0057, " Incorrect 'typename' value" },
{ E0058, " Incorrect 'typesize' value" },
{ E0059, " The identifier of a process ('proc') cannot contain spaces" },
{ E0060, " The identifier of a process ('proc') cannot contain balises" },
{ E0061, " An exception cannot be thrown out of a function" },
{ E0062, " Syntax error" },
{ E0063, " The increment value of an iteration (with step) must be numerical" },
{ E0064, " An anonymous array serving as an iterator to a for loop cannot be empty" },
{ E0065, " Wrong ternary condition format" },
{ E0066, " A 'ret' instruction must only fit on one instruction (one line = one ';')" },
{ E0067, " Division by zero" },
{ E0068, " Wrong enumeration value" },
{ E0069, " 'Upon' block members cannot contain expressions other than 'it'" },
{ E0070, " A match/case expression must contain at least one 'case' expression before using 'default'" },
{ E0071, " Unknown error" },
{ E0072, " Undefined object" },
{ E0073, " Not a valid math expression" },
{ E0074, " Expected character" },
{ E0075, " Unbalanced brackets" },
{ E0076, " Non-ascii character detected" },
{ E0077, " The current version of Arlia only accepts constant values as optional function parameters" },
{ E0078, " Undefined type" },
{ E0079, " Statement not recognised in this context" },
{ E0080, " Invalid statement" },
{ E0000, " ... " }
};
};
The *.cpp just implements the functions as follows :
ThrowError(ErrorCodes code) {
colored_message_error("[ E" + std::to_string(code) + " ]" + Messages[code], Color::yellow);
}
As you can see, the list contains 80 + 1 elements. And E0080 has 80 as index in the enumeration.
When I try to access it:
exception.ThrowError(exception.E0080);
my program doesn't seem to want to update the information. That is, the enumeration constant sent to the function: in fact, the program displays the value I set before it (E29).
It's exactly like I'm doing this:
exception.ThrowError(exception.E0029);
So, no, it's most likely not a stupid debugging or compiling problem (I still know how to use a compiler ^^). It seems strange that Visual Studio does not update this new data (how ? why ? is it ?).

Do C++ vector and Gtkmm work together perfectly?. Segmentation fault when getting values of vector<string> from gtkmm on_click method

I am in middle of creating treeview for my project using gtkmm and C++.
What I want to do is to get variable properties from my order class. And I choose to use vector to store those properties so I get them easily by calling that method in the different class such as my main_window class. I can successfully get all values from other classes except main_window class showing segmentation fault.
To run my program:
1/ type "make" in terminal
2/ type "./mice" to run program
3/ click file->test. The program crashes
main_window.cpp class:
void Main_window::on_test_click() {
std::cout<< " On _test_clicked\n";
//auto add 1 order
controller.execute_cmd(99);
//THE LINE BELOW IS NOT WORKING IN ON_TEST_CLICK
std::vector<std::string> record = controller.order_to_strings(0);
}
auto_add method from emporium. cpp
void Emporium::auto_add() {
Order order0(1);
add_order(&order0);
std::vector<std::string> record = order_to_strings(0);
std::cout << "This is printing from emporium.cpp class" <<std::endl
<< "Id:" << record[0] <<"State: "<< record[1]<<"Price:"<< record[2]<< std::endl;
}
vector methods in emporium, order, controller classes.
std::vector<std::string> Controller::order_to_strings(int index) {
emporium.order_to_strings(index);
}
std::vector<std::string> Emporium::order_to_strings(int index) {
return orders[index]->to_strings();
}
std::vector<std::string> Order::to_strings(){
std::vector<std::string> order;
order.push_back(std::to_string(id_number));
order.push_back(state.to_string());
order.push_back(std::to_string(price));
return order;
}
Error:
*** Error in `./mice': free(): invalid pointer: 0x00007fa77a295000 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fa77d63a7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7fa77d64337a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fa77d64753c]
./mice[0x406793]
./mice[0x4065cf]
./mice[0x40630a]
./mice[0x405eb7]
./mice(_ZNSt6vectorINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESaIS5_EED1Ev+0x35)[0x405b03]
......
This is my full version of my project. Test folder is my simplified version: https://github.com/dtn9797/MICE/tree/master/test
In the method auto_add(), Order object is created, which is destroyed in the end of auto_add() method. However in mean time pointer to this object is added to vector orders. This pointer point to invalid data in memory outside auto_add() method. Accessing data behind this pointer give crash.
void Emporium::auto_add() {
Order order0(1); //creating order0 local variable
add_order(&order0); //here pointer to something that will be destroyed soon is stored
std::vector<std::string> record = order_to_strings(0);
std::cout << "This is printing from emporium.cpp class" <<std::endl
<< "Id:" << record[0] <<"State: "<< record[1]<<"Price:"<< record[2]<< std::endl;
} //order0 local variable is destroyed here
void Emporium::add_order (Order* order) {
orders.push_back(order);
}
One of possible solution to prevent crash you can create Order object like this:
void Emporium::auto_add() {
add_order(new Order(1));
std::vector<std::string> record = order_to_strings(0);
std::cout << "This is printing from emporium.cpp class" <<std::endl
<< "Id:" << record[0] <<"State: "<< record[1]<<"Price:"<< record[2]<< std::endl;
}
But then for code correctness, remember to delete orders that are in std::vector<Order*> orders in the Emporium class destructor.

Generate Functions Automatically in C++?

I'm looking to automatically generate functions. For instance, could I make 50 functions named foo1 to foo50 without defining each one?
I'm using this for an interpreter for a domain specific language. Right now, I have about 80 functions that follow this general formula:
pqlsymbol * u_greedy_consen(vector<pqlsymbol * > arglist)
{
pqlsymbol * result;
if (arglist.size() == 1 && arglist[0]->is_treeset()){
result = new pqlsymbol(greedy_consen(arglist[0]->get_treeset(), 100 ) );
}
else if (arglist.size() == 2 && arglist[0]->is_treeset() && arglist[1]->is_double()){
result = new pqlsymbol(greedy_consen(arglist[0]->get_treeset(), (float)(arglist[1]->get_double()) ) );
}
else if (arglist.size() == 2 && arglist[0]->is_treeset() && arglist[1]->is_int()){
result = new pqlsymbol(greedy_consen(arglist[0]->get_treeset(), (float)(arglist[1]->get_int()) ) );
}
else {
//cout << "consensus expects 1 treeset and optinally 1 Int/Double argument. " << "Found " << get_arg_types(arglist) << endl;
result = new pqlsymbol(ERROR, "Type Error");
}
return result;
}
arglist is a list of arguments passed in at the command line. It checks the size of arglist, then check to see if the arguments are of the correct type, and then calls the appropriate function if they are.
So, I want to know if I could reduce this to a more general function. I would give it a vector of what types of arguments are expected and then a pointer to a function that would be called if those arguments are found.
So, is there a way that I could make a call like:
add_function("greedy_consen", [ [treeset], [treeset, int], [treeset, double] ], &greedy_consen)
That would create a function u_greedy_consen which automatically looks for any of the given sets of parameters, and calls greedy_consen with those parameters if found. Is that possible?
Thanks