List not a class or implementation - c++

#ifndef __LISTA_H__
#define __LISTA_H__
template<typename VALUE_TYPE>
class List {
public:
virtual unsigned int size() const = 0;
};
#endif
#include <iostream>
using namespace std;
template<typename T>
unsigned int List :: size() const {
return 0;
}
int main() {
List<int> list;
return 0;
}
I am receiving a compile error stating that the list is not a class defined when its clearly defined above:
prog.cpp:16:14: error: 'List' is not a class, namespace, or
enumeration unsigned int List :: size() const {
^ prog.cpp:5:7: note: 'List' declared here class List {
^ 1 error generated.

List is indeed not a class. It is a class template.
List<T>, for some T, is a class.
Write this:
template<typename T>
unsigned int List<T>::size() const {
// ^^^
return 0;
}
Newer GCC gives better diagnostics here, literally telling you what to do:
main.cpp:16:14: error: 'template<class VALUE_TYPE> class List' used without template arguments
16 | unsigned int List :: size() const {
Once that's fixed, you'll need to create something to derive from List<T>, because that's an abstract class, and you can't instantiate (in main) one of them.
Again, GCC is very helpful here:
main.cpp: In function 'int main()':
main.cpp:21:15: error: cannot declare variable 'list' to be of abstract type 'List<int>'
21 | List<int> list;
| ^~~~
main.cpp:5:7: note: because the following virtual functions are pure within 'List<int>':
5 | class List {
| ^~~~
main.cpp:7:26: note: 'unsigned int List<VALUE_TYPE>::size() const [with VALUE_TYPE = int]'
7 | virtual unsigned int size() const = 0;

virtual unsigned int size() const = 0;
You have created an abstract class.
An abstract class is a class that has to be inherited (Or else simply not be used), used mainly for polymorphic inheritance systems. You cannot create an instance of an abstract class because it beats the whole point of its abstractness.
List<int> list;
Here, you are creating an instance of the declared abstract class.
The class is abstract due the fact that one of its methods, size() const = 0; is abstract (because of the = 0).
Furthermore, as the comments suggest, you should recheck your understanding of how classes and templates work, and my extra suggestion is to check what an abstract class is and make sure you understand when to use such classes.
There's another issue - if you want to declare a function as a template you should add template above the function declaration inside the class declaration too.

template<typename VALUE_TYPE>
class List
{
public:
virtual unsigned int size() const
{
return 0;
}
};
#endif
#include <iostream>
using namespace std;
int main() {
List<int> list;
return 0;
}
the problem is you leave size() as an abstract class for ( future inherited class ).
You have to make another class inherited from List and implement size()
Not to implement at List class

Related

How can I declare a class template pointer in another class(in the same hpp file)?

I have defined a class template RBT_COMMON_PACKAGE and I want to create a member variable of type RBT_COMMON_PACKAGE* in another class.
I get the error:
error2955: RBT_COMMON_PACKAGE': use of class template requires template argument list
Here is the code:
template< class T , int N>
class RBT_COMMON_PACKAGE; // Forward definition
{
public:
COORDINATES start;
COORDINATES target;
RBT_CAR world_start;
RBT_CAR world_target;
//RBT_CAR_PNT via;
int prep;
int type;
}
class PROTECT
{
private:
RBT_COMMON_PACKAGE *p0;
RBT_COMMON_PACKAGE *p1;
}

pass pointer to template member of template class

I'm searching for a way to have a function of my template class which accepts as a parameter a member of the template (it could be either one of its arguments or functions).
model.h
template <class T>
class Model
{
public:
Model(){}
void relate(int T::*, int ){}
};
main.cpp
#include "model.h"
class element
{
public:
element();
char getA(){return this->a;}
int getB(){return this->b;}
char a;
int b;
};
int main(int argc, char *argv[]){
Model<element *> model;
return 0;
}
it gives the creating pointer to member of non-class type ‘element*’ error.
I agree with that since pointer must point to some defined type memory area.
My final goal is to tell my class that I want to relate a specific member of its template with some number which later will be used to order different members in a list which later will be displayed.
This wont be used with types such as Model<int> but only with other classes.
Your instantiate a Model<element*> hence this:
void relate(int T::*, int ){}
is (just hypotheically):
void relate(int element*::*, int) {}
Its a "pointer to member of a pointer type". If you instantiate a Model<element> your code works fine. Alternatively you can use std::remove_pointer<T>.
EDIT:
suddenly I'm figuring out... I used a poiter as a template...
but the game changes now...
int main(int argc, char *argv[]){
Model<element> model;
element e;
model.relate(&element::getA(), 0); // <- call to non static-member error
model.relate(&element::getB(), 0); // <- call to non static-member error
model.relate(&element::a, 0); // <- type mismatch error
model.relate(&element::b, 0); // <- no error
}

Overwriting existing type with typedef inside a class

I want to overwrite a type with a typedef. The rationale for doing this is that one of my class has lot of templates and i want to replace all calls to that class with the templatized class (so that within another class Achild means Achild<T>. However, i get an error.
template <typename T>
class Achild
{
public:
Achild<T>() = default;
};
class Foo
{
typedef Achild<int> Achild;
public:
Foo() = default;
};
int main()
{
auto foo = new Foo();
}
I get the following error:
new_test.cpp:12:22: error: declaration of ‘typedef class Achild<int> Foo::Achild’ [-fpermissive]
typedef Achild<int> Achild;
^~~~~~
new_test.cpp:2:10: error: changes meaning of ‘Achild’ from ‘class Achild<int>’ [-fpermissive]
class Achild
How can i get this to work? The example is only for sample and my reasons for doing this is also related to how i have to get this to work with an existing codebase.
You are aliasing the type with itself (Achild already a type since you declared it in your class). You should instead do:
using Child = Achild<int>;
Note that you also should use the keyword using instead of typedef since it is the equivalent (and more robust) in C++. See What is the difference between 'typedef' and 'using' in C++11?.

Extend a template classe using the type definition in subclass

I imitated the std::enable_shared_from_this to create a template class, but I made the class use the type definition in its subclass.
Unfortunately!
Although I used typename, after compiling,
//
// https://ideone.com/eYCBHW http://ideone.com/eYCBHW
#include <iostream>
#include <set>
#include <map>
using namespace std;
template<class _S> struct A {
};
template<class _Subclass>
class Global {
public:
typedef typename _Subclass::connection_t connection_t;
//std::map<std::string, _Subclass::connection_t> connections;
//std::set<_Subclass::connection_t> connections;
//using typename _Subclass::connection_t;
//typename _Subclass::connection_t* connections;
//connection_t* connections;
};
class CConnection {};
class SConnection;
class Client : public Global<Client> {
public:
typedef CConnection connection_t;
};
#if 0
class Server : public Global<Server> {
public:
typedef SConnection connection_t;
};
#endif
class SConnection {};
int main() {
// your code goes here
return 0;
}
GCC complained:
prog.cpp: In instantiation of ‘class Global<Client>’:
prog.cpp:25:23: required from here
prog.cpp:14:43: error: invalid use of incomplete type ‘class Client’
typedef typename _Subclass::connection_t connection_t;
^~~~~~~~~~~~
prog.cpp:25:7: note: forward declaration of ‘class Client’
class Client : public Global<Client> {
^~~~~~
How to solve it?
References
Where and why do I have to put the “template” and “typename” keywords?
C++ - meaning of a statement combining typedef and typename [duplicate]
Two template classes use each other as template argument
Having a typedef at class level requires the template arguments to be complete types. How would the compiler otherwise be able to check, if the type provided as argument actually has some equivalent typedef itself?
Analogously, the following is going to fail:
class C;
using G = Global<C>; // C is not a complete type!
class C // too late...
{
// ...
};
Problem with curiously recurring template pattern, which is what you're trying to implement, that at the point you try to derive, the class is not yet complete, just as in my example above:
class Client : public Global<Client> // client is not yet complete!
{
}; // only HERE, it will get complete, but that's too late for above
Ever wondered, though, why member variables are known within member functions even though being declared after the function? That's because
class C
{
void f() { n = 12; }
int n = 10;
};
is compiled as if it was written as:
class C
{
inline void f();
int n = 10;
};
void C::f() { n = 12; } // n is known now!
This is at the same time the clue where you can use the template argument the way you intend:
template<class T> // different name used! *)
class Global
{
public:
void f()
{
typedef typename T::connection_t connection_t; // possible here!
// (similar to why you can use the static cast as in the link provided)
}
};
That won't help, though, with your members:
std::map<std::string, typename T::connection_t> connections;
// ^ additionally was missing, but won't help either
T still remains incomplete at this point.
Within the comments, though, you only seem to use the connection type. If you don't need the client or server class for any reason other than the typedef, you can solve the issue pretty simply:
template<class T> // different name used! *)
class Global
{
std::map<std::string, T> connections;
// ^ use T directly
};
class Client : public Global<CConnection>
// ^ make sure it is defined BEFORE
{
// ...
};
Otherwise, you need to fall back to other means, e. g. the pimpl pattern, where you would let the implementation class inherit from the template.
*) Identifiers starting with underscore followed by captial letter, as well as those containing two subsequent identifiers, are reserved for the implementation (i. e. for use by the compiler). Defining your own such ones yields undefined behaviour.
Edit (stolen from the comments):
If you need client or server from within Global, you could provide both as separate template paramters as well:
template <typename Base, typename Connection>
{
// use Connection directly, e. g. for member definitions
// and Base within member functions as mandated by CRTP
};
class Client : public Global<Client, CConnection>
{ /* ... */ };

cannot declare variable to be of type because the following virtual functions are abstract

I have the following code
Classes.h
#ifndef CLASSES_H
#define CLASSES_H
#include <iostream>
using namespace std;
template< class T1, class T2>
class class1
{
public:
virtual void method1(int) const =0;
virtual void method2(class1&) const =0;
};
template< class T1>
class class2:public class1<T1,int>
{
public:
void method1(int) const;
void method2(class2&) const;
};
template< class T1>
void class2<T1>::method1(int i) const
{
cout<<"class2::method1 - before Call %i"<<endl;
cout<<"class2::method1 - after Call"<<endl;
}
template< class T1>
void class2<T1>::method2(class2& c2) const
{
cout<<"class2::method2 - before Call"<<endl;
cout<<"class2::method2 - after Call"<<endl;
}
#endif
main.cpp
#include <cstdlib>
#include <iostream>
using namespace std;
#include "Classes.h"
int main(int argc, char *argv[])
{
class2<int> c2;
c2.method1(0);
c2.method2(c2);
system("PAUSE");
return EXIT_SUCCESS;
}
Basically, C1 is an interface Class, therefore its methods are purely virtual. The proble am encountering is that Medhod2 passes and instance of the the class itself (which is class1 for the interface, and class2 for the class implementig such interface).
Therefore Method2 has signature
void method2(class1&) const;
in class1 and
void method2(class2&) const;
in class2.
This is the reason wihy I am getting the error below when compiling.
main.cpp: In function `int main(int, char**)':
main.cpp:12: error: cannot declare variable `c2' to be of type `class2<int>'
main.cpp:12: error: because the following virtual functions are abstract:
Classes.h:14: error: void class1<T1, T2>::method2(class1<T1, T2>&) const [with
T1 = int, T2 = int]
make: *** [main.o] Error 1
How can I fix this issue?
Can somebody please let me know? Thanks.
Your problem is that the virtual signatures need to match (return types can be co-variant, but otherwise the signatures should be the same). Change class2's void method2(class2&) const; to void method2(class1&) const;.
Alternately, hide the virtual method and supply your replacement:
class class2
{
// must be implemented since pure virtual, but now private
void method2(class1&) const;
public:
void method1(int) const;
void method2(class2&) const;
};
You have a design problem: class1::method2(class1&) const must work for any argument matching the bill, i.e. every reference to type class1. If class2 can only implement method2() for arguments of type class2, it's incomplete not only syntactically but also logically: there is no way it can deal with the intended use
class2 A;
class1*B = method_returning_pter_to_class1_object();
A.method2(*B); // intended usage of virtual function
(If you didn't intend this type of usage, then your design in class1 was flawed.)
Of course you can use a dynamic_cast to invoke special behaviour if the argument is actually of type class2&, i.e.
void class2::method(class1&x) const
{
class2*x2 = dynamic_cast<class2*>(&x);
if(x2)
apply_method_taking_class2(*x2);
else
apply_method_for_other_than_class2_object(x);
}
but this may incur some run-time penalty.