Getting inheritance issues when trying to compile - stack

I have a class called stackTester that is trying to inherit from another class stackofChars. The methods defined in stackofChars that I am trying to use in stackTester are all virtual, but when I try to use them in stackTester, I get an error
request for member which is of non-class type
Here is my stackofChars.h file:
#define STACK_OF_CHARS_H
#include "node.h"
class stackofChars
{
private:
node* m_top;
public:
//constructor for the stack, takes in no paramaters
stackofChars();
//copy constructor, takes in a referance to the original stack
stackofChars(const stackofChars& orig);
//destructor for the stack, no parameters
~stackofChars();
//destructor for the copy, takes in a referance to the copy
void operator=(const stackofChars& rhs);
//pushes the stack back and creates a new node at the stop, takes in an entry, returns nothing
virtual void push(char entry);
//deletes the top entry and pushes the stack up, takes in nothing, returns nothing
virtual void pop();
//peeks at the top entry, takes in nothing, returns a char, const because nothing is changed
virtual char peek() const;
//checks if the stack is empty, takes in no parameters, returns nothing, const because nothing is changed
virtual bool isEmpty() const;
};
#endif
Here is my stackTester.h file:
#ifndef STACK_TESTER_H
#define STACK_TESTER_H
#include "stackofChars.h"
class stackTester : public stackofChars
{
public:
stackTester();
//This will call all your test methods
void runTests();
private:
//Creates an empty stack and verifies isEmpty() returns true
void test1();
//Creates an empty stack pushes 1 value, verifies isEmpty() returns false
void test2();
//Creates an empty stack, then pushes once, pops once, and verifies isEmpty returns true
void test3();
//more test methods as needed
};
#endif
If needed, here is my stackTester.cpp file:
#include "stackTester.h"
#include "stackofChars.h"
#include <iostream>
void stackTester::test1()
{
stackofChars test();
std::cout << "Test#1: Newly created stack is empty: ";
if(test.isEmpty() == true)
{
std::cout << "Pass\n";
}
else
{
std::cout << "Fail\n";
}
}
void stackTester::test2()
{
stackofChars test();
test.push(???);
std::cout << "Test#2: Push on empty stack makes it non-empty: ";
if(test.isEmpty() == true)
{
std::cout << "Pass\n";
}
else
{
std::cout << "Fail\n";
}
}
void stackTester::test3()
{
stackofChars test();
test.push(???);
test.pop();
std::cout << "Test#3: Popping all elements makes stack empty: ";
if(test.isEmpty() == true)
{
std::cout << "Pass\n";
}
else
{
std::cout << "Fail\n";
}
}
Can someone tell me why I am getting this error?

stackofChars test(); is wrong.The right way to declare a class object should be: stackofChars test; or stackofChars test{};
There is an explanation here enter link description here

Related

Can Clang AST get the virtual function table?

I tried using CXXRecordDecl, to print the virtual functions, but they are in declaration order, which may not be the order actually in the vtable.
sample code
namespace test
{
class Foo {
public:
virtual void v_func() {}
virtual void v_func2() {}
virtual ~Foo() = default;
};
class Bar : public Foo {
public:
virtual void v_func2() {}
virtual void v_func() {}
virtual ~Bar() = default;
};
} // namespace test
int main() {
test::Foo *foo = new test::Bar();
test::Bar *bar = new test::Bar();
delete foo;
delete bar;
return 0;
}
The virtual function table printed by gdb is as follows:
(gdb) info vtbl foo
vtable for 'test::Foo' # 0x65a450 (subobject # 0x101a008):
[0]: 0x404402 <test::Bar::v_func()>
[1]: 0x4043f4 <test::Bar::v_func2(int, test::tmp)>
(gdb) info vtbl bar
vtable for 'test::Bar' # 0x65a450 (subobject # 0x101a010):
[0]: 0x404402 <test::Bar::v_func()>
[1]: 0x4043f4 <test::Bar::v_func2(int, test::tmp)>
By traversing the method of CXXRecordDecl, it can only print in the order of function declaration.
// CXXRecordDecl *cxx_record
// Dump out all the virtual methods
for (CXXRecordDecl::method_iterator first = cxx_record->method_begin();
first != cxx_record->method_end(); ++first) {
if (!first->isVirtual()) {
continue;
}
llvm::outs() << first->getQualifiedNameAsString() << " " << first->getType().getAsString() << "\n";
}
out:
v_func void (void)
v_func2 void (int, class test::tmp)
~Foo void (void) noexcept
v_func2 void (int, class test::tmp)
v_func void (void)
~Bar void (void) noexcept
I checked the documentation for CXXRecordDecl and found nothing related to vtables

C++ Templated class function that can detect std::vector

If I have a templated class, I can do the following to detect if a vector was passed:
template<typename T> struct is_vector { static const bool value=false; };
template<typename T> struct is_vector<std::vector<T>> { static const bool value=true; };
template<class T>
class Parser {
public:
Parser() {}
void parse(T obj) {
if (is_vector<T>::value) {
std::cout << "vector\n";
//obj.push_back(T {});
}
else {
std::cout << "not vector\n";
}
}
};
int main() {
Parser<int> p1;
p1.parse(123);
Parser<std::vector<int>> p2;
p2.parse({ 1, 2, 3});
return 0;
}
Output:
not vector
vector
I can detect a vector, yet the compiler complains when I uncomment the push_back call:
main.cpp: In instantiation of ‘void Parser<T>::parse(T) [with T = int]’:
main.cpp:26:14: required from here
main.cpp:15:17: error: request for member ‘push_back’ in ‘obj’, which is of non-class type ‘int’
obj.push_back(T {});
~~~~^~~~~~~~~
Obviously, an int does not have a push_back function, but the vector does. The is_vector call is evaluated at runtime, but the push_back is caught at compile time.
With partial template specialization, I can do what I want:
template<typename T>
void parse(T obj) {
std::cout << "not vector: " << obj << "\n";
}
template<typename T>
void parse(std::vector<T> obj) {
std::cout << "is vector\n";
for (auto i : obj) std::cout << i << " ";
obj.push_back(T {});
std::cout << "\n";
for (auto i : obj) std::cout << i << " ";
std::cout << "\n";
}
int main() {
parse(1);
parse('a');
parse(std::vector<int> { 1, 2, 3 });
return 0;
}
Output:
not vector: 1
not vector: a
is vector
1 2 3
1 2 3 0
So, how can I combine these 2 ideas, either at compile-time or at runtime? That is, have a templated class with a function that can handle vectors and non-vectors?
What you're looking for is a new feature in C++17, if constexpr. It's the same as a regular if, except that the condition is evaluated at compile time, and when instantiating the branch(es) will discard the non-taken branch at compile time. The discarded branch does not need to well-formed. So, for your example:
template<class T>
class Parser {
public:
Parser() {}
void parse(T obj) {
if constexpr (is_vector<T>::value) {
std::cout << "vector\n";
obj.push_back(T {});
}
else {
std::cout << "not vector\n";
}
}
};
See Difference between if constexpr vs if for some more talk on the differences. You can also read the cppreference page on if statements to get a detailed overview of some of the nitty-gritty details.

Storing multiple types into class member container

I was reading this Q/A here and as my question is similar but different I would like to know how to do the following:
Let's say I have a basic non template non inherited class called Storage.
class Storage {};
I would like for this class to have a single container (unordered multimap) is where I'm leaning towards... That will hold a std::string for a name id to a variable type T. The class itself will not be template. However a member function to add in elements would be. A member function to add might look like this:
template<T>
void addElement( const std::string& name, T& t );
This function will then populate the unorderd multimap. However each time this function is called each type could be different. So my map would look something like:
"Hotdogs", 8 // here 8 is int
"Price", 4.85f // here 4.8f is float.
How would I declare such an unorderd multimap using templates, variadic parameters, maybe even tuple, any or variant... without the class itself being a template? I prefer not to use boost or other libraries other than the standard.
I tried something like this:
class Storage {
private:
template<class T>
typedef std::unorderd_multimap<std::string, T> DataTypes;
template<class... T>
typedef std::unordered_multimap<std::vector<std::string>, std::tuple<T...>> DataTypes;
};
But I can not seem to get the typedefs correct so that I can declare them like this:
{
DataTypes mDataTypes;
}
You tagged C++17, so you could use std::any (or std::variant if the T type can be a limited and know set of types`).
To store the values is simple.
#include <any>
#include <unordered_map>
class Storage
{
private:
using DataTypes = std::unordered_multimap<std::string, std::any>;
DataTypes mDataTypes;
public:
template <typename T>
void addElement (std::string const & name, T && t)
{ mDataTypes.emplace(name, std::forward<T>(t)); }
};
int main()
{
Storage s;
s.addElement("Hotdogs", 8);
s.addElement("Price", 4.85f);
// but how extract the values ?
}
But the problem is that now you have a element with "Hotdogs" and "Price" keys in the map, but you have no info about the type of the value.
So you have to save, in some way, a info about the type of th value (transform the value in a std::pair with some id-type and the std::any?) to extract it when you need it.
I've done something along those lines, the actual solution is very specific to your problem.
That being said, I'm doing this on a vector, but the principle applies to maps, too.
If you're not building an API and hence know all classes that will be involved you could use std::variant something along the lines of this:
#include <variant>
#include <vector>
#include <iostream>
struct ex1 {};
struct ex2 {};
using storage_t = std::variant<ex1, ex2>;
struct unspecific_operation {
void operator()(ex1 arg) { std::cout << "got ex1\n";}
void operator()(ex2 arg) { std::cout << "got ex2\n";}
};
int main() {
auto storage = std::vector<storage_t>{};
storage.push_back(ex1{});
storage.push_back(ex2{});
auto op = unspecific_operation{};
for(const auto& content : storage) {
std::visit(op, content);
}
return 0;
}
which will output:
got ex1
got ex2
If I remember correctly, using std::any will enable RTTI, which can get quite expensive; might be wrong tho.
If you provide more specifics about what you actually want to do with it, I can give you a more specific solution.
for an example with the unordered map:
#include <variant>
#include <unordered_map>
#include <string>
#include <iostream>
struct ex1 {};
struct ex2 {};
using storage_t = std::variant<ex1, ex2>;
struct unspecific_operation {
void operator()(ex1 arg) { std::cout << "got ex1\n";}
void operator()(ex2 arg) { std::cout << "got ex2\n";}
};
class Storage {
private:
using map_t = std::unordered_multimap<std::string, storage_t>;
map_t data;
public:
Storage() : data{map_t{}}
{}
void addElement(std::string name, storage_t elem) {
data.insert(std::make_pair(name, elem));
}
void doSomething() {
auto op = unspecific_operation{};
for(const auto& content : data) {
std::visit(op, content.second);
}
}
};
int main() {
auto storage = Storage{};
storage.addElement("elem1", ex1{});
storage.addElement("elem2", ex2{});
storage.addElement("elem3", ex1{});
storage.doSomething();
return 0;
}

Why is it Segmentation fault every time?

This code gives error only in runtime and it's "Segmentation fault". How can this be tackled? I don't have any idea how to remove this error. Thanks in Advance!
#include <iostream>
#include <cstddef>
using namespace std;
class Node
{
private:
int data;
Node* nextNodeAddress;
public:
Node(): nextNodeAddress(NULL) {} // if next node is not used it must be null.
void setData(int); // this function sets data in the node
int retrieveData(); // this function retrieves the data from the node
};
void Node::setData(int data)
{ this->data=data; }
class List
{
private:
Node* headNode;
Node* currentNode;
int listSize;
public:
List();
void addNode(int);
void deleteNode(int);
};
List::List(): headNode(NULL),currentNode(NULL)
{
}
void List::addNode(int data)
{
Node* newNode = NULL;
newNode->setData(data);
newNode->setNextNode(NULL);
if(headNode==NULL)
headNode = newNode;
else
currentNode->setNextNode(newNode);
currentNode = newNode;
this->listSize++;
}
GCC with all warnings on throws this:
In member function ‘void Node::setData(int)’:
18:28: warning: declaration of ‘data’ shadows a member of 'this' [-Wshadow]
void Node::setData(int data)
Might be a good place to start checking.
Edit: The issue is discussed here, basically you're reusing the name data in both private int in the class definition and int data as the parameter for the method. How could it possibly decide which one is which when you do this->data = data?

rewrite codes which matches a certain ASTMatcher

I'm new to clang and I want to rename member variable name using ASTMatcher. For example:
class Person
{
public:
....
private:
char m_genger;
^^^^^^^^ => rename to gender_
int m_age;
^^^^^^ => rename to age_
};
After reading some tutorials now I found how to use ASTMatcher, so that I can access location to be modified.
But I got a Seg. Fault right after calling clang::Rewriter::ReplaceText or InsertText.
My ASTMatcher Program
DeclarationMatcher FieldDeclMatcher =
clang::ast_matchers::fieldDecl().bind("field_decl");
clang::Rewriter rewriter;
class MyMatcher : public MatchFinder::MatchCallback
{
public :
MyMatcher(clang::Rewriter& rewrite) : m_rewriter(rewrite) {}
virtual void run(const MatchFinder::MatchResult& result)
{
if (const clang::FieldDecl* fs
= result.Nodes.getNodeAs<clang::FieldDecl>("field_decl"))
{
std::cout << "===== found: FieldDecl =====" << std::endl;
fs->dump();
std::cout << std::endl;
// seg. fault occurs here.
m_rewriter.InsertText(fs->getLocStart(), "/* comment */", true, true);
}
}
private:
clang::Rewriter& m_rewriter;
};
int main(int argc, const char **argv)
{
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
MyMatcher matcher(rewriter);
clang::ast_matchers::MatchFinder finder;
finder.addMatcher(FieldDeclMatcher, &matcher);
return Tool.run(newFrontendActionFactory(&finder).get());
}
Output of gdb backtrace
#0 0x0000000000a52153 in clang::Rewriter::getLocationOffsetAndFileID(clang::SourceLocation, clang::FileID&) const ()
#1 0x0000000000a5516a in clang::Rewriter::InsertText(clang::SourceLocation, llvm::StringRef, bool, bool) ()
#2 0x0000000000422f0d in MyMatcher::run(clang::ast_matchers::MatchFinder::MatchResult const&) () at ex03.cc:68
Thanks.
After reading Eli Bendersky's post, I found the answer.
It seems like that I can't rewrite codes only using ASTMatcher, To modify code, we need not only ASTFrontendAction and ASTConsumer but ASTMatcher.
(please correct me, if I'm wroing)
You can get Eli's code his github repository.

Resources