I'm having some problems implementing a class based on a abstract parent class. It's saying PolishStack is an abstract class, even though all virtual functions are coded:
In file included from braincalc.cpp:10:
./polstack.h:15:7: error: explicit specialization of non-template class 'PolishStack'
class PolishStack<T> : public AbstractStack<T> {
^ ~~~
braincalc.cpp:13:21: error: variable type 'PolishStack<char>' is an abstract class
PolishStack <char> stk;
^
./abstractstack.h:53:16: note: unimplemented pure virtual method 'isEmpty' in
'PolishStack'
virtual bool isEmpty() const = 0;
Here's my class header:
#ifndef POLSTACK_H
#define POLSTACK_H
#include <iostream>
using namespace std;
#include "abstractstack.h"
template <typename T>
class PolishStack<T> : public AbstractStack<T> {
T* data;
int mMax;
int mTop;
public:
PolishStack();
bool isEmpty();
const T& top() const throw (Oops);
void push(const T& x);
void pop();
void clear();
//my funcs:
void printStack();
~PolishStack();
};
#endif
I don't want to give all my code away due to other students cheating, so I'll post the function that the error is complaining about:
#include "polstack.h"
//...
template <typename T>
bool PolishStack<T>::isEmpty() {
if(mTop == 0)
return true;
return false;
}
//...
As others have stated it should be:
template<typename T>
class PolishStack : public AbstractStack<T>
./abstractstack.h:53:16: note: unimplemented pure virtual method 'isEmpty' in
'PolishStack'
virtual bool isEmpty() const = 0;
You're missing the const:
template<typename T>
bool PolishStack<T>::isEmpty() const
// ^^^^^
{
if(mTop == 0)
return true;
return false;
}
Note: You should use the override keyword to be informed when you try to override a function using a different signature (i.e., you're introducing a new function overload instead of overriding the virtual one).
template<typename T>
class PolishStack : public AbstractStack<T>
{
public:
...
bool isEmpty() const override;
...
};
It's hard to tell without all the code, but one thing I noticed is that this:
class PolishStack<T> : public AbstractStack<T> {
should be just:
class PolishStack : public AbstractStack<T> {
That'll fix the first error for sure and potentially (but maybe not) the second.
Try changing to
template <typename T>
class PolishStack : public AbstractStack<T>
As a side note: Exception specifiers throw (Oops) are deprecated.
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
I'm having trouble using template member functions and template variables. The goal is to create an template for an interface which can be inherited and linked to one or more services initialized at runtime. This interface would also pass data to these specialized services (e.g. MyService). For a simpler example, with this code:
#include <string>
class Interface
{
public:
template <class T> bool init(T *_Service) {AttachService(*_Service);} //This function does other stuff too.
template <typename T> void AttachService(T _Service) { m_AttachedService<T> = *_Service; }
template <typename T> T AttachedService() { return m_AttachedService; }
protected:
template<typename T> static T m_AttachedService;
class InterfaceListener
{
void Received()
{
int a = 1;
std::string b = "hello";
AttachedService().setA(a);
m_AttachedService.setB(b);
};
};
};
class Service
{
Service();
~Service();
virtual void init() = 0;
};
class MyService : public Service, public Interface
{
MyService();
~MyService();
private:
int A;
std::string B;
protected:
Interface x;
public:
void init() { x.init(this);}
void setA(int a) { A = a; }
void setB(std::string b) { B = b; }
};
int main();
{
MyService myserv;
myserv.init();
}
I get the following errors:
C2672: 'Interface::AttachedService': no matching overloaded function found
C2783: 'T Interface::AttachedService(void)': could not deduce template argument for 'T'
C2228: left of '.setA' must have class/struct/union
C3245: 'Interface::m_AttachedService': use of a variable template requires template argument list
Any help understanding proper usage of templates would be appreciated!
Let's start with a minimal program that builds and runs without doing anything useful.
#include <string>
class Interface
{
};
class Service
{
protected:
Service() {}
~Service() {}
virtual void init() = 0;
};
class MyService : public Service, public Interface
{
private:
int A;
std::string B;
protected:
Interface x;
public:
MyService() {}
~MyService() {}
void init() {}
void setA(int a) { A = a; }
void setB(std::string b) { B = b; }
};
int main()
{
MyService myserv;
myserv.init();
}
You'll notice that there are few changes from your posted code to get to that baseline.
Interface is empty.
The member functions of Service are in public section. The default constructor and the destructor of Service have an empty implementation.
The default constructor and the destructor of MyService are in the public section of the class and they have empty implementations.
MyService::init() has an empty implementation.
Now we can start adding more code.
I changed MyService::init() to:
void init() { x.init(this); }
With no other changes, I got the following compiler error.
socc.cc: In member function ‘virtual void MyService::init()’:
socc.cc:25:23: error: ‘class Interface’ has no member named ‘init’
void init() { x.init(this);}
Now, Interface needs to be updated with an init function.
I added a dummy implementation to move the process forward.
class Interface
{
public:
template <class T> bool init(T *_Service) { return true; }
};
Time to add something useful to Interface::init(). Changing it to
template <class T> bool init(T *_Service)
{
AttachService(*_Service);
return true;
}
produces the following compiler error, which is not surprising.
socc.cc: In instantiation of ‘bool Interface::init(T*) [with T = MyService]’:
socc.cc:31:32: required from here
socc.cc:8:23: error: ‘AttachService’ was not declared in this scope
AttachService(*_Service);
~~~~~~~~~~~~~^~~~~~~~~~~
Time to add AttachService. Changing Interface to (closing matching what you have)
class Interface
{
public:
template <class T> bool init(T *_Service)
{
AttachService(*_Service);
return true;
}
template <typename T> void AttachService(T _Service)
{
m_AttachedService<T> = *_Service;
}
protected:
template<typename T> static T m_AttachedService;
};
produces the following compiler error.
socc.cc: In instantiation of ‘void Interface::AttachService(T) [with T = MyService]’:
socc.cc:8:10: required from ‘bool Interface::init(T*) [with T = MyService]’
socc.cc:39:32: required from here
socc.cc:14:33: error: no match for ‘operator*’ (operand type is ‘MyService’)
m_AttachedService<T> = *_Service;
^~~~~~~~~
That makes sense. In AttachServie, _Service is not a pointer.
Changing Inteface::AttachService to:
template <typename T> void AttachService(T _Service)
{
m_AttachedService<T> = _Service;
}
makes the compiler error go away but there is a linker error.
:socc.cc:(.rdata$.refptr._ZN9Interface17m_AttachedServiceI9MyServiceEE[.refptr._ZN9Interface17m_AttachedServiceI9MyServiceEE]+0x0): undefined reference to `Interface::m_AttachedService<MyService>'
collect2: error: ld returned 1 exit status
That makes sense since we have not defined the static member variable.
Adding the following line
template<typename T> T Interface::m_AttachedService;
right after definition of Interface takes care of the linker error.
The following is the next version of the complete program that builds successfully and runs even though it still doesn't do anything useful.
#include <string>
class Interface
{
public:
template <class T> bool init(T *_Service)
{
AttachService(*_Service);
return true;
}
template <typename T> void AttachService(T _Service)
{
m_AttachedService<T> = _Service;
}
protected:
template<typename T> static T m_AttachedService;
};
template<typename T> T Interface::m_AttachedService;
class Service
{
protected:
Service() {}
~Service() {}
virtual void init() = 0;
};
class MyService : public Service, public Interface
{
private:
int A;
std::string B;
protected:
Interface x;
public:
MyService() {}
~MyService() {}
void init() { x.init(this); }
void setA(int a) { A = a; }
void setB(std::string b) { B = b; }
};
int main()
{
MyService myserv;
myserv.init();
}
Time to add your version of the AttachedService to Interface
template <typename T> T AttachedService() { return m_AttachedService; }
That produces the following compiler error.
socc.cc: In member function ‘T Interface::AttachedService()’:
socc.cc:17:73: error: missing template arguments before ‘;’ token
template <typename T> T AttachedService() { return m_AttachedService; }
That makes sense since m_AttachedService is not a member variable but a member variable template.
Changing that to
template <typename T> T AttachedService() { return m_AttachedService<T>; }
removes that error.
Now the final piece in Interface. The nested class InterfaceListener that you have posted does sound right. You have
class InterfaceListener
{
void Received()
{
int a = 1;
std::string b = "hello";
AttachedService().setA(a);
m_AttachedService.setB(b);
};
};
Problems in that class:
AttachedService() is not right since it a member function template. You have to provide a template parameter to use it.
Also, AttachedService() is not a static member function. You need an instance of Interface to make that call.
m_AttachedService is not a member variable. It is a member variable template. You have to provide a template parameter to use it.
The functions setA() and setB() are valid only if the template parameter is MyService. It does not make sense to have code in that function that is specific to a type.
I'll leave it for you to ponder over how you intend to use InterfaceListener and define its functions appropriately. Until then the following program builds and runs for me.
#include <string>
class Interface
{
public:
template <class T> bool init(T *_Service)
{
AttachService(*_Service);
return true;
}
template <typename T> void AttachService(T _Service)
{
m_AttachedService<T> = _Service;
}
template <typename T> T AttachedService() { return m_AttachedService<T>; }
protected:
template<typename T> static T m_AttachedService;
};
template<typename T> T Interface::m_AttachedService;
class Service
{
protected:
Service() {}
~Service() {}
virtual void init() = 0;
};
class MyService : public Service, public Interface
{
private:
int A;
std::string B;
protected:
Interface x;
public:
MyService() {}
~MyService() {}
void init() { x.init(this); }
void setA(int a) { A = a; }
void setB(std::string b) { B = b; }
};
int main()
{
MyService myserv;
myserv.init();
}
KSetBase.h base class , an interface
#ifndef HW6_GTUSETBASE_H
#define HW6_GTUSETBASE_H
class KSet;
#include <cstddef>
namespace TU {
template<typename T>
class KSetBase {
public:
virtual bool empty() const = 0;
virtual size_t size() const = 0; //int is not okay since unsigned also could be in.
//comparisons would be not working if that was case
//detailed
//https://stackoverflow.com/questions/1181079/stringsize-type-instead-of-int
virtual size_t max_size() const = 0;
virtual void insert(T first, T second) = 0; //cift dondurmesi gerekli
virtual void erase(T deleter) = 0;
virtual void clear() = 0;
virtual T find(T deneme) = 0;
virtual size_t count(T testle) = 0;
virtual T begin() = 0;
virtual T end() = 0;
protected:
~GTUSetBase() {
//do nothing
}
};
}
#endif //HW6_GTUSETBASE_H
KSet.h (derived class)
#include "KSetBase.h"
#ifndef HW6_GTUSET_H
#define HW6_GTUSET_H
#include <memory>
using namespace std;
namespace TU {
template<typename T>
class KSet : public KSetBase {
public:
bool empty() const;
size_t size() const;
size_t max_size() const;
void insert(T first);
void erase(T deleter);
void clear();
T find(T deneme);
size_t count(T testle);
T begin();
T end();
protected:
int hmany = 0;
shared_ptr<T> set_harmony;
};
}
#endif //HW6_GTUSET_H
I cant figure out what part of my code is wrong. I basically made a basic inheritance from interface class, which i implemented all functions in KSet.cpp. In theory nothing looks wrong but it gives 2 errors.
both in main.cpp and KSet.cpp
class KSet : public KSetBase {
Error line is this.
I checked #ifndef and #defines, i thought about using forward declaration but i cant seems to work that out.I am really stuck with this problem. I searched whole web about it , in the end there's always a big error on syntax or something that is visible , but i can't figure out on mine. It's very short and simple code.
KSetBase is a template class, if you inherit from it you must specify a template argument:
template<typename T>
class KSet : public KSetBase<T>
In addition, it seems you have a typo in the base class destructor.
template <typename T>
class BaseQueue
{
public :
virtual void push_back(T value) = 0;
//other virtual methods
};
template <typename T>
class BaseDeque: public virtual BaseQueue<T>
{
public:
virtual void push_front(T value) = 0;
//other virtual methods
};
//Realisation
template <typename T>
class VectorQueue: public BaseQueue<T>
{
typedef typename std::vector<T> array;
private: array adata;
public:
VectorQueue()
{
adata = array();
}
void push_back(T value)
{
adata.push_back(value);
}
};
template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>//,
{
void push_front(T value)
{
VectorQueue::adata.push_front(value);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
VectorDeque<int> vd = VectorDeque<int>();//here is a error
int i;
std::cin >> i;
return 0;
}
I have such error: "C2259: 'VectorDeque' : cannot instantiate abstract class ...". How can I fix it? Class VectorQueue has realize every virtual method of BaseQueue class already. But the compiler doesn't know it. The only way I see is to write something like this:
template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>//,
{
void push_front(T value)
{
VectorQueue::adata.push_front(value);
}
void push_back(T value)
{
VectorQueue::push_back(value);
}
//repeat it fo every virtual method of BaseQueue class (interface)
};
But it's awful.
push_back from BaseQueue isn't implemented on the BaseDeque side of the inheritance chain, and thus the childmost class is still abstract.
I think you're trying to force a class relationship here that shouldn't exist. Note how in the standard library deque and vector are distinct container types and things like queue adapt those containers to very precise interfaces rather than trying to inherit.
Even if you solve your diamond issue (or follow #Mark B's advice and keep them separate), you have a few other issues in there:
template <typename T>
class VectorQueue: public BaseQueue<T>
{
typedef typename std::vector<T> array;
private: array adata; // if this is private, VectorDeque can't reach it
public:
// constructors have an initializer section
// member variables should be initialized there, not in the body
VectorQueue()
// : adata() // however, no need to explicitly call default constructor
{
// adata = array();
}
};
template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>
{
void push_front(T value)
{
// if adata is protected, you can just access it. No need for scoping
/*VectorQueue::*/ adata.push_front(value);
// Error: std::vector doesn't have a method push_front.
// Perhaps you meant to use std::list?
}
};
Multiple inheritance and static polymorphism are of help, for instance:
// Abstract bases
template <typename T, typename Val>
class BaseQueue
{
public :
void push_back(Val val)
{
static_cast<T*>(this)->push_back(val);
}
// ...
};
template <typename T, typename Val>
class BaseDeque
{
public:
void push_front(Val val)
{
static_cast<T*>(this)->push_front(val);
}
// ...
};
// Concrete class
#include <deque>
template <typename Val>
class QueueDeque:
public BaseQueue<QueueDeque<Val>, Val>,
public BaseDeque<QueueDeque<Val>, Val>
{
std::deque<Val> vals;
public:
void push_front(Val val)
{
vals.push_front(val);
}
void push_back(Val val)
{
vals.push_back(val);
}
// etc..
};
int main()
{
QueueDeque<int> vd;// no more error
vd.push_front(5);
vd.push_back(0);
return 0;
}
I'm trying to use the pimpl idiom to hide some grungy template code, but I can't give derived classes of the body class friend access to the handle class. I get an error C2248 from MSVC 9 sp1. Here's some code to duplicate the error:
//
// interface.hpp
//
namespace internal{
template<class T>
class specific_body;
}
class interface
{
struct body;
body *pbody_;
interface(body *pbody);
template<class T>
friend class internal::specific_body;
public:
~interface();
interface(const interface &rhs);
bool test() const;
static interface create( bool value );
};
//
// interface.cpp
//
struct interface::body
{
virtual ~body(){}
virtual bool test() const = 0;
virtual interface::body *clone() const = 0;
};
class true_struct {};
class false_struct {};
namespace internal {
template< class T>
class specific_body : public interface::body
{ // C2248
public:
specific_body(){}
virtual bool test() const;
virtual interface::body *clone() const
{
return new specific_body();
}
};
bool specific_body<true_struct>::test() const
{
return true;
}
bool specific_body<false_struct>::test() const
{
return false;
}
} //namespace internal
interface::interface(body *pbody) : pbody_(pbody) {}
interface::interface(const interface &rhs) : pbody_(rhs.pbody_->clone()) {}
interface::~interface() { delete pbody_; }
bool interface::test() const
{
return pbody_->test();
}
interface interface::create(bool value )
{
if ( value )
{
return interface(new internal::specific_body<true_struct>());
}
else
{
return interface(new internal::specific_body<false_struct>());
}
}
//
// main.cpp
//
// #include "interface.hpp"
//
int _tmain(int argc, _TCHAR* argv[])
{
interface object( interface::create(true));
if ( object.test() )
{
// blah
}
else
{
}
return 0;
}
Any help would be appreciated, I'm trying to hide interface::body and specific_body implementations from the users of interface if that's not obvious from my question.
You need to add template<> in the explicit instantiation of the template test method
template<> // add this line
bool specific_body<true_struct>::test() const
{
return true;
}
You haven't qualified specific_body. Try
template<class T>
friend class internal::specific_body;
as your friend declaration.
Try using typename maybe? I think I read in Sutter that typename will work to get to class inside of an unknown scope, while class won't.
In addition to the unqualified specific_body mentioned by Troubadour, your specialization attempt of specific_body<>::test for true_struct and false_struct seems incorrect. You have to specialice the full class.
To solve the problem, I'd simply declare body in the public section. Declaring specific_body to be a friend of interface::body in addition doesn't help either.
Well, I was able to "solve" this problem by making the body a public declaration in the interface. That solves the C2248 error during the declaration of the specific_body. I also made the body a friend to the interface class and added a method to the body struct:
static interface create( body *pbody )
{
return interface(pbody);
}
so that a specific_body can create an interface if there is a nested relationship between instances of specific_body