I use MinGW latest version to compile the following code. I get the folowing message
y:/bbom/source/om0/basic/test.cpp: In static member function 'static void somecl
ass::init(class_object*)':
y:/bbom/source/om0/basic/test.cpp:68:50: error: no matching function for call to
'class_object::add_method(void (&)(object*, arch&))'
y:/bbom/source/om0/basic/test.cpp:68:50: note: candidate is:
y:/bbom/source/om0/basic/test.cpp:27:54: note: template<class p_function> void c
lass_object::add_method(typename p_function::funcion_type)
make.exe: *** [y:/bbom/bin/om0/basic/test.a] Error 1
Here is my code undressed from every thing not needed for this question
#include <exception>
class exception : public std::exception
{
public:
exception() {}
exception(const exception &);
~exception() throw() {}
virtual const char *what() const throw();
};
typedef unsigned id, version;
class class_object;
class object
{
public:
virtual ~object() {}
void *get_method(id);
class_object *get_class_object();
};
class class_object : public object
{
public:
template <class p_function>
void add_method(typename p_function::funcion_type p)
{add_method2((void *)p, p_function::function_id);}
void add_method2(void *, id);
};
template <typename p_func, id p_id>
class function
{
public:
typedef p_func function_type;
enum {function_id = p_id, };
function(object *p) {m_func = (p_func)p->get_method(p_id);}
p_func m_func;
};
class iface : public object
{
public:
iface(object *p) : m_object(p) {}
static void init(class_object *) {}
object *m_object;
};
class arch;
class archivable : public iface
{
public:
typedef void (*archive_func_type)(object *, arch &);
typedef function<archive_func_type, 0x5afeb287> archive_type;
archivable(object *);
archive_type archive;
};
class someclass : public object
{
public:
static void archive(object *, arch &)
{
}
static void init(class_object *p)
{
p->add_method<archivable::archive_type>(archive);
// the compiler says this call cannot be matched to
// add_method declared in class 'class_object'
}
};
What is wrong with my call to the template method in class_object::add_method<...>()
It appears you mistyped function_type as funcion_type on line 27 of test.cpp.
Typo. funcion_type should be function_type.
Related
BreadthSearchableContainer.hpp
template <typename Data>
class BreadthSearchableContainer{
public:
virtual ~BreadthSearchableContainer() = default;
BreadthSearchableContainer& operator=(const BreadthSearchableContainer&) = delete;
BreadthSearchableContainer& operator=(BreadthSearchableContainer&&) noexcept = delete;
bool operator==(const BreadthSearchableContainer&) const noexcept = delete;
bool operator!=(const BreadthSearchableContainer&) const noexcept = delete;
using typename SearchableContainer<Data>::MapFunctor;
virtual void MapBreadth(MapFunctor, void*) = 0;
using typename SearchableContainer<Data>::FoldFunctor;
virtual void FoldBreadth(FoldFunctor, const void*, void*) const = 0;
};
binarytree.hpp
template <typename Data>
class BinaryTree : virtual public BreadthSearchableContainer<Data>{
public:
struct Node {
public:
friend class BinaryTree<Data>;
virtual Node& LeftChild() = 0;
};
};
binarytreelnk.hpp
template <typename Data>
class BinaryTreeLnk : public BinaryTree<Data>{
public:
struct NodeLnk : public BinaryTree<Data>::Node{
protected:
Data Elements;
struct NodeLnk* left_child;
struct NodeLnk* right_child;
public:
friend class BinaryTreeLnk<Data>;
NodeLnk& LeftChild() override;
};
protected:
struct NodeLnk* Nodelnk_root;
};
binarytreelnk.cpp
template<typename Data>
typename BinaryTreeLnk<Data>::NodeLnk& BinaryTreeLnk<Data>::NodeLnk::LeftChild(){
if(left_child == nullptr){
throw std::out_of_range("Figlio sinisto non esistente");
}
else{
return Node(left_child);
}
}
MAIN
void main(){
BinaryTreeLnk<int> binary;
}
ERROR
binarytreelnk.hpp:58:14: error: return type of virtual function 'LeftChild' is not covariant
with the return type of the function it overrides ('lasd::BinaryTreeLnk<int>::NodeLnk &' is not derived from
'lasd::BinaryTree<int>::Node &')
NodeLnk& LeftChild() override;
~~~~~~~~ ^
binarytree.hpp:55:19: note: overridden virtual function is here
virtual Node& LeftChild() = 0;
I tell you right now that the project I’m doing is really huge and I don’t know if I was able to compress the necessary code to understand the error. However, this error could also concern compiler problems since to other colleagues of mine such a thing does not come out even with the code perfectly equal to mine. I have avoided putting includes as I know for certain that they have been inserted perfectly. If you can tell me why this mistake I would be very grateful. thanks in advance
The following code
#include <iostream>
template<typename T>
class Abstract
{
public:
virtual ~Abstract()
{}
virtual void func(const T ¶m) const = 0;
};
class Concrete : public Abstract<int*>
{
public:
virtual void func(const int *¶m) const override // watch out!
{}
};
int main()
{
Concrete c;
}
produces the following compile error at the line marked with the comment:
error C3668: 'Concrete::func' : method with override specifier 'override' did not override any base class methods
If I remove the override, this error will be shown:
error C2259: 'Concrete' : cannot instantiate abstract class
How to derive from Abstract<int*>?
Declare Concrete like this:
class Concrete : public Abstract<int*>
{
public:
virtual void func(int * const ¶m) const override
{}
};
The question is: Which part of the parameter of Abstract<int*>::f() is const?
The answer: Since T is const and T in Abstract<int*> is a pointer (to an int), it is the pointer that is const - not the int.
You want this:
virtual void func(int * const ¶m) const override // watch out!
I use swig to wrap c++ classes to ruby code. Some of my classes return std:vector of other classes so I use the std_vector.i for that.
%include "std_vector.i"
namespace std {
%template(VectorString) vector<string>;
%template(VectorField) vector<TruckBoris::Field>;
%template(VectorStructure) vector<TruckBoris::Structure>;
%template(VectorEnum) vector<TruckBoris::Enum>;
}
For the classes Enum and Structure I have this kind of warnings:
parser.cpp:2781:9: warning: destination for this 'memset' call is a pointer to dynamic class 'TruckBoris::Enum'; vtable pointer will be overwritten [-Wdynamic-class-memaccess]
memset(v_def,0,sizeof(Type));
^
parser.cpp:2807:66: note: in instantiation of member function 'swig::traits_as<TruckBoris::Enum, swig::pointer_category>::as' requested here
return traits_as< Type, typename traits< Type >::category >::as(obj, te);
^
parser.cpp:4236:92: note: in instantiation of function template specialization 'swig::as<TruckBoris::Enum>' requested here
std::vector<TruckBoris::Enum,std::allocator< TruckBoris::Enum > >::value_type val = swig::as<std::vector<TruckBoris::Enum,std::allocator< TruckBoris::Enum > >::value_type>( elem...
^
parser.cpp:2781:9: note: explicitly cast the pointer to silence this warning
memset(v_def,0,sizeof(Type));
^
(void*)
This is just some warnings and my extension is compiling and working as expected. But if there are some warnings I think it means that maybe I am wrong somewhere.
For informations:
I don't have warnings from simple classes like field but I have warning form Enum and Structure classes which both inherit from the same class. Here is the code:
class TagDeclaration
{
public:
TagDeclaration(clang::TagDecl * var);
~TagDeclaration(){}
void setPtr(clang::TagDecl * var); //for ruby interface
clang::TagDecl * getPtr() const; //for ruby interface
std::string getName() const;
bool hasNameForLinkage()const;
bool hasLinkage() const;
std::string getTypedefName() const;
std::string getRaw( clang::SourceManager & sm, const clang::LangOptions & lopt) const;
virtual TagDeclaration& Equals( const TagDeclaration & tag);
protected:
clang::TagDecl * m_var;
};
class Structure : public TagDeclaration
{
public:
Structure();
Structure(clang::TagDecl * var);
~Structure() {}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
virtual Structure& Equals(const Structure& tag);
#pragma clang diagnostic pop
std::string getTagType() const;
int getFieldsNumber() const;
std::vector<Field> getFields() const;
clang::FieldDecl * getField(int i) const;
private:
std::string m_tagType;
};
Edit :
I can reproduce this kind of error with this:
test.h
class Number {
public:
Number()
{
m_num = 0;
}
Number(int a): m_num(a) {}
~Number() {}
virtual void equals(){}
private:
int m_num;
};
class Float : public Number{
public:
Float(): Number() {}
Float(int a): Number(a) {}
~Float() {}
virtual void equals() {}
void printToto(){}
};
class Double : public Number {
public:
Double(): Number() {}
Double(int a): Number(a) {}
~Double() {}
virtual void equals() {}
void printTata();
};
test.i
%module "test"
%include "std_vector.i"
%{
#include "test.h"
%}
namespace std {
%template(VectorFloat) vector<Float>;
};
%include "test.h"
extconf.rb
require "mkmf"
CONFIG['CXX']='clang++'
create_makefile("test")
I am a C++ noob and I have a noob question.
I have an abstract tree class definition in a header file. I know it is abstract because it contains virtual methods. It looks like so:
//AbsTree.h
class AbsTree {
public:
AbsTree();
virtual ~AbsTree() =0;
virtual void accept(Visitor &visitor) const = 0;
virtual void execute(Env &ctxt) const throw (InappropriateFunction);
};
class Operation: public AbsTree{
public:
Operation(char oper);
virtual ~Operation();
virtual void accept (Visitor &visitor) const;
char getOperator() const;
private:
char operator;
};
I have come up with the following implementation of this AbsTree:
AbsTree.cpp
#include "AbsTree.h"
AbsTree::AbsTree() {}
AbsTree::~AbsTree() {}
AbsTree::accept(Visitor &visitor) const{}
AbsTree::execute(Env &ctxt) const {}
Operation::Operation(char oper): operator(oper) {}
Operation::~Operation(){}
Operation::accept(Visitor &visitor) const{}
char Operation::getOperator() {
return operator;
}
So I try to compile the .cpp via:
g++ AbsTree.cpp -o AbsTree
and I get
AbsTree.cpp:3:1: error: 'AbsTree' does not name a type
AbsTree.cpp:4:1: error: 'AbsTree' does not name a type
AbsTree.cpp:5:1: error: 'AbsTree' does not name a type
AbsTree.cpp:6:1: error: 'AbsTree' does not name a type
AbsTree.cpp:8:1: error: 'Operation' does not name a type
AbsTree.cpp:9:1: error: 'Operation' does not name a type
AbsTree.cpp:10:1: error: 'Operation' does not name a type
AbsTree.cpp:11:6: error: 'Operation' has not been declared
AbsTree.cpp: In function 'char getOperator()':
AbsTree.cpp:12:9: error: 'operator' was not declared in this scope
Please expose me for the C++ noob that I am.
Here's a compilable/runnable version of your code (runnable at ideone here)
struct Visitor { };
struct Env { };
struct InappropriateFunction { };
class AbsTree {
public:
AbsTree();
virtual ~AbsTree() =0;
virtual void accept(Visitor &visitor) const = 0;
virtual void execute(Env &ctxt) const throw (InappropriateFunction);
};
class Operation: public AbsTree{
public:
Operation(char oper);
virtual ~Operation();
virtual void accept (Visitor &visitor) const;
char getOperator() const;
private:
char operator_;
};
AbsTree::AbsTree() {}
AbsTree::~AbsTree() {}
void AbsTree::accept(Visitor &visitor) const{}
void AbsTree::execute(Env &ctxt) const throw (InappropriateFunction) {}
Operation::Operation(char oper): operator_(oper) {}
Operation::~Operation(){}
void Operation::accept(Visitor &visitor) const{}
char Operation::getOperator() const {
return operator_;
}
int main()
{
Operation o('x');
Visitor my_visitor;
o.accept(my_visitor);
o.getOperator();
}
Basically, you've got to take more care to make sure the functions you define match your declarations - that includes const and throw specifications and return type. Further, operator is a reserved keyword and you can not use it to name your own variables.
Separately, exception specifications are deprecated... best to leave them out as they never proved useful. (C++11 has a noexcept keyword that's occasionally useful if you want to make it clear that a function can be used in code making exception guarantees - might get a little extra optimisation too, but if an exception is raised in/under the function your program will call std::terminate).
AbsTree is an abstract class, like you said. This means that you need to create a derived class in order to provider an implementation.
// ConcreteTree.h
#include "AbsTree.h"
class ConcreteTree : public AbsTree {
public:
ConcreteTree();
virtual ~ConcreteTree();
virtual void accept(Visitor &visitor) const;
virtual void execute(Env &ctxt) const throw (InappropriateFunction);
}
Then:
// ConcreteTree.cpp
#include "ConcreteTree.h"
ConcreteTree::ConcreteTree() {}
ConcreteTree::~ConcreteTree() {}
ConcreteTree::accept(Visitor &visitor) const{}
ConcreteTree::execute(Env &ctxt) const {}
class ZooAnimal {
public:
virtual void draw();
int resolveType() {return myType;}
protected:
int myType;
};
class Bear : public ZooAnimal {
public:
Bear (const char *name) : myName(name), myType(1){}
void draw(){ };
private:
std::string myName;
};
void main()
{
}
When I am compiling above code I am geeting following error
error C2614: 'Bear' : illegal member initialization: 'myType' is not a base or member
Why am I getting the above error, as we can access protected member from the derived class?
You can't initialize base class member in derived class initializer lists.
You'll need to provide a constructor to the base class:
class ZooAnimal {
public:
ZooAnimal(int type) : myType(type) {}
virtual void draw();
int resolveType() {return myType;}
protected:
int myType;
};
and call it from the derived class:
class Bear : public ZooAnimal {
public:
//here//
Bear (const char *name) : ZooAnimal(1), myName(name) {}
void draw(){ };
private:
std::string myName;
};