Cython: error: no matching function for call to … - c++

I'm taking my first steps in Cython to write a Python extension of some C++ code. Also, I have only superficial knowledge of C++. Now I face an error which I do not understand, when cythonizing my .pyx file. The C++11 code is generated successfully, but that code does not compile. The first lines of the compiler error message are:
$ python setup.py build_ext --inplace
Compiling py_foo.pyx because it changed.
[1/1] Cythonizing py_foo.pyx
running build_ext
building 'pyfoo' extension
creating build
creating build/temp.linux-x86_64-3.9
gcc -pthread -B /home/…/compiler_compat -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -Wall -fPIC -O2 -isystem /home/…/include -I/home/…/include -fPIC -O2 -isystem /home/…/include -fPIC -I. -I./ -I/home/…/include/python3.9 -c ./example.cpp -o build/temp.linux-x86_64-3.9/./example.o -std=c++11
gcc -pthread -B /home/…/compiler_compat -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -Wall -fPIC -O2 -isystem /home/…/include -I/home/…/include -fPIC -O2 -isystem /home/…/include -fPIC -I. -I./ -I/home/…/include/python3.9 -c ./foo.cpp -o build/temp.linux-x86_64-3.9/./foo.o -std=c++11
gcc -pthread -B /home/…/compiler_compat -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -Wall -fPIC -O2 -isystem /home/…/include -I/home/…/include -fPIC -O2 -isystem /home/…/include -fPIC -I. -I./ -I/home/…/include/python3.9 -c py_foo.cpp -o build/temp.linux-x86_64-3.9/py_foo.o -std=c++11
py_foo.cpp: In function ‘void __pyx_pf_5pyfoo_9PyDerived_2__dealloc__(__pyx_obj_5pyfoo_PyDerived*)’:
py_foo.cpp:1913:24: warning: deleting object of polymorphic class type ‘nspace::Derived’ which has non-virtual destructor might cause undefined behavior [-Wdelete-non-virtual-dtor]
1913 | delete __pyx_v_self->c_derived;
| ^~~~~~~~~
py_foo.cpp: In function ‘int __pyx_pf_5pyfoo_5PyFoo___cinit__(__pyx_obj_5pyfoo_PyFoo*, __pyx_obj_5pyfoo_PyBase*)’:
py_foo.cpp:2134:66: error: no matching function for call to ‘std::unique_ptr<nspace::Base>::unique_ptr(PyObject*&)’
2134 | __pyx_t_2 = new nspace::Foo(((std::unique_ptr<nspace::Base> )__pyx_t_1));
| ^~~~~~~~~
In file included from /usr/include/c++/9/memory:80,
from py_foo.cpp:729:
/usr/include/c++/9/bits/unique_ptr.h:281:2: note: candidate: ‘template<class _Up, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::auto_ptr<_Up>&&)’
281 | unique_ptr(auto_ptr<_Up>&& __u) noexcept;
| ^~~~~~~~~~
/usr/include/c++/9/bits/unique_ptr.h:281:2: note: template argument deduction/substitution failed:
py_foo.cpp:2134:66: note: mismatched types ‘std::auto_ptr<_Up>’ and ‘PyObject*’ {aka ‘_object*’}
2134 | __pyx_t_2 = new nspace::Foo(((std::unique_ptr<nspace::Base> )__pyx_t_1));
|
...
These are the relevant files of my MWE:
example.h:
#ifndef EXAMPLE_H
#define EXAMPLE_H
namespace nspace
{
class Base
{
public:
virtual void print_() const = 0;
};
class Derived : public Base
{
private:
int i;
public:
Derived(int i);
void print_() const;
};
}
#endif /* EXAMPLE_H */
example.cpp:
#include <iostream>
#include "example.h"
namespace nspace
{
Derived::Derived(int i)
{
this->i = i;
}
void Derived::print_() const
{
std::cout << this->i << std::endl;
}
}
foo.h:
#ifndef FOO_H
#define FOO_H
#include <memory>
#include "example.h"
namespace nspace
{
class Foo
{
public:
Foo();
Foo(std::unique_ptr<Base> base);
void print_();
private:
std::unique_ptr<Base> base;
};
}
#endif // FOO_H
foo.cpp:
#include "foo.h"
#include "example.h"
namespace nspace
{
Foo::Foo()
{
this->base = std::unique_ptr<Base>(new Derived(0));
}
Foo::Foo(std::unique_ptr<Base> base)
{
this->base = std::move(base);
}
void Foo::print_()
{
this->base->print_();
}
}
cpp_foo.pxd:
from libcpp.memory cimport unique_ptr
cdef extern from "foo.h" namespace "nspace":
cdef cppclass Foo:
Foo() except +
Foo(unique_ptr[Base] cpp_base) except +
print_()
cdef extern from "example.h" namespace "nspace":
cdef cppclass Base:
pass
cdef cppclass Derived(Base):
Derived(int i) except +
py_foo.pyx:
# distutils: language = c++
# distutils: extra_compile_args = -std=c++11
cimport cython
from cpp_foo cimport Foo, Base, Derived
from libcpp.memory cimport unique_ptr
cdef class PyBase:
pass
cdef class PyDerived(PyBase):
cdef Derived* c_derived
def __cinit__(self, int i):
self.c_derived = new Derived(i)
def __dealloc__(self):
del self.c_derived
cdef class PyFoo:
cdef Foo* foo
def __cinit__(self, PyBase py_base):
self.foo = new Foo(
cpp_base=<unique_ptr[Base]>(py_base.c_derived)
)
def __dealloc__(self):
del self.foo
def print_(self):
self.foo.print_()
setup.py:
from distutils.core import setup, Extension
from Cython.Build import cythonize
extensions = [
Extension("pyfoo",
sources=[
"py_foo.pyx",
"./foo.cpp",
"./example.cpp",
],
include_dirs=["./"]
)
]
setup(
ext_modules=cythonize(
extensions,
language_level=3,
),
)
I'm very sure my error comes from a misconception I have regarding Cython (and maybe C++ too). Any help or tip is appreciated.

There's a few problems. I've listed three that I've spotted quickly but there may well be more.
The cast
I think you want to call unique_ptr rather than cast to it
cpp_base=unique_ptr[Base](py_base.c_derived)
The <> cast generates a C-style cast which the C++ compiler doesn't know what to do with.
py_base doesn't have an attribute c_derived
Therefore this'll default to assuming that c_derived is a Python attribute returning a Python object.
PyDerived has the attribute c_derived. If you want to access this attribute then the argument to PyFoo.__cinit__ needs to be of type PyDerived.
Ownership
By wrapping py_base.c_derived with a unique_ptr you're passing ownership to the unique_ptr. Despite this, py_base still believes it owns this pointer and will delete it in __dealloc__.

Related

Missing '#include "m1.hpp"'; 'my_type' must be defined before it is used

There is a m1.hpp header file defining my_type. The header is included by m2 module. The module exports my_class (has a member of my_type) used in main. How can I fix the compilation issue (see below) without including m1.hpp (that would defeat the purpose) in main? (I'm using clang from trunk).
// file: m1.hpp
#pragma once
class my_type {};
// file: m2.cppm
module;
#include "m1.hpp"
export module m2;
export class my_class { my_type m; };
// file: main.cpp
import m2;
int main() { my_class c; }
clang++ -fmodules-ts -std=c++2a -fprebuilt-module-path=. --precompile m2.cppm -o m2.pcm
clang++ -fmodules-ts -std=c++2a -fprebuilt-module-path=. -c m2.pcm -o m2.obj
clang++ -fmodules-ts -std=c++2a -fprebuilt-module-path=. -c main.cpp -o main.obj
In file included from main.cpp:2:
m2.cppm:5:14: error: missing '#include "m1.hpp"'; 'my_type' must be defined before it is used
export class my_class { my_type m; };
^
main.cpp:3:23: note: in implicit default constructor for 'my_class' first required here
int main() { my_class c; }
^
m1.hpp:3:7: note: previous definition is here
class my_type {};
^
1 error generated.

Workaround for Clang "exception specification is not available until end of class definition" bug

Given this code:
template <typename>
struct Check { constexpr static bool value = true; };
struct A {
A() noexcept(Check<int>::value) = default;
};
Compiling with various versions of GNU g++ works fine, but it always fails with clang++ 5.0.1 (both with libstdc++ and libc++):
$ g++-4.9.4 test.cpp -c -o test -std=c++11 -Wall -Wextra
$ g++-5.4.0 test.cpp -c -o test -std=c++11 -Wall -Wextra
$ g++-6.4.0 test.cpp -c -o test -std=c++11 -Wall -Wextra
$ g++-7.2.0 test.cpp -c -o test -std=c++11 -Wall -Wextra
$ clang++ test.cpp -c -o test -std=c++11 -Wall -Wextra -Weverything
test.cpp:2:16: warning: 'constexpr' specifier is incompatible with C++98 [-Wc++98-compat]
struct Check { constexpr static bool value = true; };
^
test.cpp:5:39: warning: defaulted function definitions are incompatible with C++98 [-Wc++98-compat]
A() noexcept(Check<int>::value) = default;
^
test.cpp:5:9: warning: noexcept specifications are incompatible with C++98 [-Wc++98-compat]
A() noexcept(Check<int>::value) = default;
^
test.cpp:5:5: error: exception specification is not available until end of class definition
A() noexcept(Check<int>::value) = default;
^
test.cpp:5:18: note: in instantiation of template class 'Check<int>' requested here
A() noexcept(Check<int>::value) = default;
^
3 warnings and 1 error generated.
$ clang++ test.cpp -c -o test -std=c++11 -Wall -Wextra
test.cpp:5:5: error: exception specification is not available until end of class definition
A() noexcept(Check<int>::value) = default;
^
test.cpp:5:18: note: in instantiation of template class 'Check<int>' requested here
A() noexcept(Check<int>::value) = default;
^
1 error generated.
On Compiler Explorer this also seems to work for all versions of GCC newer 4.7.0 (including trunk), but fails for all Clang versions except for Clang 3.4.0, 3.5.0, 3.5.1 and trunk. So this seems like Clang bug.
Is it possible to work around this bug? How? Is this bug already tracked somewhere?
EDIT:
I tracked this bug down to Clang PR23383. As of now there is no notice about this being fixed in Clang although it seems to work with Clang trunk in Compiler Explorer.
This might be related to PR30860 (and C++ DR1330 as described in Richard Smith's comment on PR30860). It seems that the issue has something to do about when the contents of the noexcept() are parsed.
And so it turns out that one obvious workaround is to try to force the compiler to parse these contents elsewhere. One possible solution would be to provide the contents noexcept() as a constexpr member constant:
template <typename>
struct Check { constexpr static bool value = true; };
struct A {
A() noexcept(workaround) = default;
private: /* Work around Clang PR23383: */
static constexpr bool workaround = Check<int>::value;
};
Unfortunately, this does not work in all cases, e.g. such as this:
#include <type_traits>
struct Base { virtual ~Base() noexcept; };
struct OuterClass {
class InnerDerived: public Base {
private:
static constexpr auto const workaround =
std::is_nothrow_default_constructible<Base>::value;
public:
InnerDerived() noexcept(workaround);
};
class InnerDerived2: public InnerDerived {
private:
static constexpr auto const workaround2 =
std::is_nothrow_default_constructible<InnerDerived>::value;
public:
InnerDerived2() noexcept(workaround2);
};
};
The latter yields the error even when using Clang trunk in Compiler Explorer. Any ideas why?

undefined reference to vtable for inheriting classes

I'm trying to develop a neural network in c++.
I refactored my code utilizing class-inheritance, to allow me to have different kinds of layers, whose neurons could be iterated over in sequence.
My problem is, that my linker (ld invoked by g++) complaines about undefined references to vtables and typeinfo-objects.
As far as I know, the error "undefined reference to vtable for class" comes from not implemented pure virtual methods in base classes, but unfortunately I not was able locate the error more percisely.
make all:
g++ -Wall -fmessage-length=0 --std=c++11 -w -c -o Test2dSparselyNeuralNet.o Test2dSparselyNeuralNet.cpp
g++ -Wall -fmessage-length=0 --std=c++11 -w -c -o NeuralNet.o NeuralNet.cpp
g++ -Wall -fmessage-length=0 --std=c++11 -w -c -o Sparsely2dNeuralNetwork.o Sparsely2dNeuralNetwork.cpp
g++ -Wall -fmessage-length=0 --std=c++11 -w -c -o Connection.o Connection.cpp
g++ -Wall -fmessage-length=0 --std=c++11 -w -c -o Layer2d.o Layer2d.cpp
g++ -Wall -fmessage-length=0 --std=c++11 -w -c -o Neuron2dIterator.o Neuron2dIterator.cpp
g++ -Wall -fmessage-length=0 --std=c++11 -w -c -o input/2dinput/cross/cross.o input/2dinput/cross/cross.cpp
g++ -o bin/neural_net_2d Test2dSparselyNeuralNet.o NeuralNet.o Sparsely2dNeuralNetwork.o Connection.o Layer2d.o Neuron2dIterator.o input/2dinput/cross/cross.o
Layer2d.o: In function `Layer::Layer()':
Layer2d.cpp:(.text._ZN5LayerC2Ev[_ZN5LayerC5Ev]+0x13): undefined reference to `vtable for Layer'
Layer2d.o: In function `Iterator::Iterator()':
Layer2d.cpp:(.text._ZN8IteratorC2Ev[_ZN8IteratorC5Ev]+0xf): undefined reference to `vtable for Iterator'
Layer2d.o: In function `Layer::~Layer()':
Layer2d.cpp:(.text._ZN5LayerD2Ev[_ZN5LayerD5Ev]+0x13): undefined reference to `vtable for Layer'
Layer2d.o:(.rodata._ZTI7Layer2d[_ZTI7Layer2d]+0x10): undefined reference to `typeinfo for Layer'
Neuron2dIterator.o:(.rodata._ZTI16Neuron2dIterator[_ZTI16Neuron2dIterator]+0x10): undefined reference to `typeinfo for Iterator'
collect2: error: ld returned 1 exit status
make: *** [neural_net_2d] Error 1
makefile:
CXXFLAGS = -Wall -fmessage-length=0 --std=c++11 -w
CXXFLAGS_DEBUG = -g -Wall -fmessage-length=0 --std=c++11 -w
SAMPLES = input/2dinput/cross/cross.o
OBJS = Test2dSparselyNeuralNet.o NeuralNet.o Sparsely2dNeuralNetwork.o Connection.o Layer2d.o Neuron2dIterator.o ${SAMPLES}
LIBS =
TARGET = neural_net_2d
$(TARGET): $(OBJS)
$(CXX) -o bin/$(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
debug: $(OBJS)
$(CXX) -o bin/$(TARGET) $(OBJS) $(LIBS) $(CXXFLAGS_DEBUG)
clean:
rm -f $(OBJS) $(TARGET)
Layer.h
#ifndef LAYER_H
#define LAYER_H
#include "Neuron.h"
#include "Iterator.h"
class Layer
{
protected:
// biasNeuron
Neuron biasNeuron = 1.0;
public:
inline Layer() : biasNeuron(1.0) {}
virtual Iterator& start();
virtual Neuron& front(void);
virtual Neuron& back(void);
virtual int size();
protected:
private:
};
#endif // LAYER_H
Layer2d.h
#ifndef LAYER2D_H
#define LAYER2D_H
#include "Layer.h"
class Layer2d : public Layer
{
public: std::vector<std::vector<Neuron> > _neurons;
public:
Layer2d();
virtual ~Layer2d();
Iterator& start();
Neuron& front(void);
Neuron& back(void);
int size();
protected:
private:
};
#endif // 2DLAYER_H
Layer2d.cpp
#include "Layer2d.h"
#include "Neuron2dIterator.h"
class Neuron2dIterator;
Iterator& Layer2d::start(void)
{
Neuron2dIterator& it = (*new Neuron2dIterator(*this));
return it;
}
Neuron& Layer2d::front(void)
{
Neuron& frontNeuron = this->_neurons.front().front();
return frontNeuron;
}
Neuron& Layer2d::back(void)
{
Neuron& backNeuron = this->_neurons.back().back();
return backNeuron;
}
int Layer2d::size(void)
{
int size = this->_neurons.back().size() * this->_neurons.size();
return size;
}
Layer2d::Layer2d()
{
//ctor
}
Layer2d::~Layer2d()
{
//dtor
}
LineLayer.h
#ifndef LINELAYER_H
#define LINELAYER_H
#include "Layer.h"
#include "Neuron.h"
#include <vector>
using namespace std;
class LineIterator;
class LineLayer : public Layer
{
public: std::vector<Neuron> _neurons;
public:
LineLayer();
protected:
private:
};
#endif // LINELAYER_H
LineLayer.cpp
#include "LineLayer.h"
#include "LineIterator.h"
Iterator& LineLayer::start()
{
LineIterator& it = (*new LineIterator());
return it;
}
Neuron& LineLayer::front()
{
Neuron& frontNeuron = this->_neurons.front();
return frontNeuron;
}
Neuron& LineLayer::back()
{
Neuron& backNeuron = this->_neurons.back();
return backNeuron;
}
int LineLayer::size()
{
return this->_neurons.size();
}
LineLayer::LineLayer()
{
//ctor
}
LineLayer::~LineLayer()
{
//dtor
}
Thnx for help!
As explained at https://gcc.gnu.org/wiki/VerboseDiagnostics#missing_vtable the vtable will be in the same object file as the first non-inline virtual function, which is Layer::start. You haven't defined that function, so the compiler never generated the vtable.
To fix the linker error be sure you have provided a definition for the first non-inline virtual function declared in the class.

Makefile C++ inheritance

The following are the files involved and a short description:
arrayListType.h, arrayListTypeImp.cpp: declare and implement arrayListType class and its functions.
unorderedarrayListType.h unorderedArrayListTypeImp.cpp: inherit arrayListType class and declare unorderedarrayListType class and implement virtual functions of arrayListType class.
Ch13_Ex6.cpp: Instantiates an object of class unorderedArrayListType and runs some tests.
I am having a compilation error, which I think is due to the Makefile. The following is the error:
unorderedArrayListTypeImp.cpp:4: error: expected unqualified-id before 'using'
unorderedArrayListTypeImp.cpp: In member function 'virtual void unorderedArrayListType::insertAt(int, int)':
unorderedArrayListTypeImp.cpp:11: error: 'cout' was not declared in this scope
unorderedArrayListTypeImp.cpp:11: error: 'endl' was not declared in this scope
unorderedArrayListTypeImp.cpp:13: error: 'cout' was not declared in this scope
Line 4 has a using namespace std; command. The line before that is #include "arrayListType.h". I have tried the following variations in the Makefile but neither worked:
Version 1
all: Ch13_Ex6
arrayListTypeImp.o: arrayListType.h arrayListTypeImp.cpp
g++ -c -Wall arrayListType.h arrayListTypeImp.cpp
unorderedArrayListTypeImp.o: arrayListTypeImp.o unorderedArrayListType.h unorderedArrayListTypeImp.cpp
g++ -c -Wall arrayListTypeImp.o unorderedArrayListType.h unorderedArrayListTypeImp.cpp
Ch13_Ex6.o: Ch13_Ex6.cpp
g++ -c -Wall Ch13_Ex6.cpp
Ch13_Ex6: arrayListTypeImp.o unorderedArrayListTypeImp.o Ch13_Ex6.o
g++ -Wall Ch13_Ex6.o arrayListTypeImp.o unorderedArrayListTypeImp.o -o Ch13_Ex6
Version 2:
all: Ch13_Ex6
arrayListTypeImp.o: arrayListType.h arrayListTypeImp.cpp
g++ -c -Wall arrayListType.h arrayListTypeImp.cpp
unorderedArrayListTypeImp.o: unorderedArrayListType.h unorderedArrayListTypeImp.cpp
g++ -c -Wall unorderedArrayListType.h unorderedArrayListTypeImp.cpp
Ch13_Ex6.o: Ch13_Ex6.cpp
g++ -c -Wall Ch13_Ex6.cpp
Ch13_Ex6: arrayListTypeImp.o unorderedArrayListTypeImp.o Ch13_Ex6.o
g++ -Wall Ch13_Ex6.o arrayListTypeImp.o unorderedArrayListTypeImp.o -o Ch13_Ex6
Both versions compile arrayListTypeImp.o and give the error shown above when compiling unorderedArrayListTypeImp.o. The following is the complete compile output:
make
g++ -c -Wall unorderedArrayListType.h unorderedArrayListTypeImp.cpp
arrayListTypeImp.o
unorderedArrayListType.h:16: error: expected unqualified-id at end of input
unorderedArrayListTypeImp.cpp:4: error: expected unqualified-id before 'using'
unorderedArrayListTypeImp.cpp: In member function 'virtual void unorderedArrayListType::insertAt(int, int)':
unorderedArrayListTypeImp.cpp:11: error: 'cout' was not declared in this scope
unorderedArrayListTypeImp.cpp:11: error: 'endl' was not declared in this scope
unorderedArrayListTypeImp.cpp:13: error: 'cout' was not declared in this scope
unorderedArrayListTypeImp.cpp:13: error: 'endl' was not declared in this scope
Code for arrayListType.h:
#ifndef H_arrayListType
#define H_arrayListType
class arrayListType
{
public:
bool isEmpty() const;
bool isFull() const;
int listSize() const;
int maxListSize() const;
void print() const;
bool isItemAtEqual(int location, int item) const;
virtual void insertAt(int location, int insertItem) = 0;
virtual void insertEnd(int insertItem) = 0;
void removeAt(int location);
int retrieveAt(int location) const;
virtual void replaceAt(int location, int repItem) = 0;
void clearList();
virtual int seqSearch(int searchItem) const = 0;
virtual void remove(int removeItem) = 0;
arrayListType(int size = 100);
arrayListType(const arrayListType& otherList);
virtual ~arrayListType();
protected:
int *list;
int length;
int maxSize;
};
#endif
Code for unorderArrayListTypeImp.cpp:
#include <iostream>
#include "unorderedArrayListType.h"
using namespace std;
void unorderedArrayListType::insertAt(int location,
int insertItem)
{
if (location < 0 || location >= maxSize)
cout << "The position of the item to be inserted "
<< "is out of range." << endl;
else if (length >= maxSize) //list is full
cout << "Cannot insert in a full list" << endl;
else
{
for (int i = length; i > location; i--)
list[i] = list[i - 1]; //move the elements down
list[location] = insertItem; //insert the item at
//the specified position
length++; //increment the length
}
} //end insertAt
void unorderedArrayListType::insertEnd(int insertItem)
{
if (length >= maxSize) //the list is full
cout << "Cannot insert in a full list." << endl;
else
{
list[length] = insertItem; //insert the item at the end
length++; //increment the length
}
} //end insertEnd
// More virtual functions implemented and finally a constructor
unorderedArrayListType::unorderedArrayListType(int size)
: arrayListType(size)
{
} //end constructor
You did not #include <iostream> in arrayListType.h, but did it in arrayListType.cpp, before you #include "arrayListType.h" there. You need to place #include <iostream> into arrayListType.h before you use std::cout or std::endl.
To avoid such mistakes it is good to place the interface header as the first #include statement int the implementation file.
I am guessing that the error is in unorderedArrayListType.h, you likely have a missing semicolon or something. Looking in the Makefile will do nothing to solve that error.
EDIT: Woah, there actually is something wrong with your Makefile! Heh, I just looked at it and you have the following:
g++ -c -Wall arrayListType.h arrayListTypeImp.cpp
Don't pass .h files to g++!, only the .cpp files. So write it like this:
g++ -c -Wall arrayListTypeImp.cpp
Likewise:
g++ -c -Wall unorderedArrayListType.h unorderedArrayListTypeImp.cpp
should be:
g++ -c -Wall unorderedArrayListTypeImp.cpp
Evan Teran is probably right. expected unqualified-id before '...' usually means you missed a semicolon before that line. If it turns out it really is your makefile, here's some general makefile advice:
Use variables. Instead of
g++ -c -Wall ...
you can do
CXX_OPTS= -Wall -O3
...
g++ -c $(CXX_OPTS) ...
Use pattern rules. Rather than
arrayListTypeImp.o: arrayListType.h arrayListTypeImp.cpp
g++ -c -Wall arrayListType.h arrayListTypeImp.cpp
unorderedArrayListTypeImp.o: unorderedArrayListType.h unorderedArrayListTypeImp.cpp
g++ -c -Wall unorderedArrayListType.h unorderedArrayListTypeImp.cpp
Ch13_Ex6.o: Ch13_Ex6.cpp
g++ -c -Wall Ch13_Ex6.cpp
you can use
%.o:%.cpp
g++ $(CXX_OPTS) -c $< -o $#
This should shorten your makefile and make it easier to debug and find your problem. If you want more information, check this out.

ffs does not name a type in C++

I get compilation error when i try to compile the following..... Please comment.
Here is my code:
ffs.h
#ifndef FFS_H
#define FFS_H
#include <iostream>
#include <string>
#include "commands.h"
class ffs{
private:
Filesystem *filesys;
Superblock block;
void processCommands(InputParser command);
void performQuit();
void performInit(InputParser command);
public:
void acceptCommands();
ffs(){};
};
#endif
ffs.cpp
#include "ffs.h"
void ffs::acceptCommands(){
std::string input;
while(true){
std::cout<< "Enter command : ";
getline(std::cin,input);
InputParser parser(input);
processCommands(parser);
}
}
void ffs::performInit(InputParser command){
command.getCommand().pop_front();
int n = atoi(command.getCommand().front().c_str());
std::cout<< n << " : number of blocks "<<std::endl;
command.getCommand().pop_front();
int m = atoi(command.getCommand().front().c_str());
std::cout<<m << " : number of inode blocks" << std::endl;
command.getCommand().pop_front();
block.ninode=m;
Filesystem fs(n);
filesys = &fs;
}
void ffs::performQuit(){
///filesys->clean();
exit(0);
}
void ffs::processCommands(InputParser command){
std::string cmd=command.getCommandName();
if(cmd.compare(commands::Q())==0) performQuit();
else if (cmd.compare(commands::INIT())==0) performInit(command);
}
tester.h
#ifndef TESTER_H
#define TESTER_H
#include "ffs.h"
class ffs;
class tester{
private:
ffs ffsobj;
public:
void run(){ffsobj.acceptCommands()};
};
#endif
tester.cpp
#include "tester.h"
int main()
{
tester runner;
runner.run();
return 0;
}
ERROR:
g++ -c -Wall tester.cpp
tester.h:7: error: ffs does not name a type
tester.h: In member function void tester::run():
tester.h:9: error: ffsobj was not declared in this scope
tester.h:9: error: expected `;' before ˜} token
make: *** [tester.o] Error 1
Makefile:
CFLAGS=-c -Wall
CC=g++
all: flags.o InputParser.o commands.o Filesystem.o ffs.o tester.o
$(CC) flags.o InputParser.o commands.o Filesystem.o ffs.o tester.o -o runner.o
flags.o : flags.cpp flags.h
$(CC) $(CFLAGS) flags.cpp
InputParser.o : InputParser.cpp InputParser.h
$(CC) $(CFLAGS) InputParser.cpp
ffs.o: ffs.cpp ffs.h
$(CC) $(CFLAGS) ffs.cpp
commands.o: commands.cpp commands.h
$(CC) $(CFLAGS) commands.cpp
Filesystem.o: Filesystem.cpp Filesystem.h Superblock.h
$(CC) $(CFLAGS) Filesystem.cpp
tester.o: tester.cpp tester.h ffs.o
$(CC) $(CFLAGS) tester.cpp
#fileUtility.o : IFileUtility.h
# gcc -c IFileUtility.h
# Inode.h commands.h Filesystem.h
clean :
rm *.o
You can't use ffs as your class name, it already has a meaning in c++ (albiet an obscure one). Just pick a different name.
You got a #endif in your ffs.h file, without the befinning #if.
If you include ffs.h in your tester.h file, why do you declare class ffs; ?
Error is in following line:
class ffs;
class tester{
private:
ffs ffsobj; // <--- can't declare object for ffs; can be pointer/reference only
To declare an object of ffs type, class tester should be able to see its full definition. Otherwise you can just declare a pointer or reference of ffs type, if you have forward declared like that (ffs* or ffs&).
Remove the forward class declaration class ffs; from tester.h. It is unnecessary since you include ffs.h and then confuses the compiler when it tries to define a class member which it thinks it has not seen the definition for.
do not solve the "does not name a type" problem, but look at this line:
void run(){ffsobj.acceptCommands()};
the correct is:
void run(){ffsobj.acceptCommands();}