I'm trying to make the following bit of code to work...
#include <list>
template <typename T>
class container{
public:
virtual T func_x(){
T temp;
//do stuff with list<t> test
return temp;
}
private:
std::list<T> test;
};
template <typename T>
class container2 : public container<T>{
public:
virtual T func_x(){
T temp;
//do different stuff with list<T> test
return temp;
}
};
What I want to be able to do is declare
container<T> x;
container2<T> y;
And be able to have y have access to all the public functions of x, except that it behaves differently for func_x.
The problem I have now is that func_x in class container2 cannot use;
std::list<T> test;
I have even tried making class container completely public. Still no dice. Can this be done?
Thanks!
Members are by default private for classes:
template <typename T>
class container2 : public container<T>{
//************
// no modifier
virtual T func_x(){
T temp;
//do different stuff with list<T> test
return temp;
}
private:
std::list<T> test;
};
means that func_x is private, since no modifier is specified.
You need to explicitly declare func_x as public, as you have for class container.
"Just because it's public in the base class doesn't mean it's automatically that way for the derived".
EDIT:
If you want base class members to be accessible in derived classes, you must declare them either protected or public. So, to answer your follow-up question, change
private:
std::list<T> test;
to
protected:
std::list<T> test;
Also, in the future, don't edit the question to ask a new one. You should create a new question to deal with the new issue. It can be misleading for others who see answers that no longer apply to the new question.
You need to add public: to your class declaration: otherwise, all members declared are private by default.
template <typename T>
class container2 : public container<T>{
public: // <<==== ADD THIS
virtual T func_x(){
T temp;
//do different stuff with list<T> test
return temp;
}
private:
std::list<T> test;
};
The problem is that your func_x is hidden by your derived object, because you've redefined it, as private in derived.
You need to make it public.
Related
Is it possible to declare a templated class in C++ along with the classes it inherits from? Basically I want to give the compiler a hint, that my templated class will always inherit another at declaration time.
Maybe some code will clear up why this is a problem for me:
template<typename T>
class GrandparentClass
{
public:
T grandparentMember;
};
//this needs to be only a declaration, since I do not want classes of ParentClass with random T
template<typename T>
class ParentClass : public GrandparentClass<T>
{
};
// this does not work:
//template<typename T>
//class ParentClass : public GrandparentClass<T>;
// this does not either, because then the child class cannot access the variable from the grandparent class
//template<typename T>
//class ParentClass;
template<>
class ParentClass<int> : public GrandparentClass<int>
{
public:
ParentClass()
{
grandparentMember = 5;
}
};
template <typename T>
class ChildClass : public ParentClass<T>
{
public:
void foo()
{
std::cout << grandparentMember << "\n";
}
};
Also, I cannot use C++ 11.
EDIT:
I found an easy way out of this:
template<typename T>
class ParentClass : public GrandparentClass<T>
{
public:
ParentClass() { ParentClass::CompilerError(); };
};
Just do not define CompilerError() method in the class and everything's fine.
A class declaration is only really useful for non-value variable declarations, like pointers and references. You can't access the class members or even instantiate it, though. Even if you knew that a declared class inherits from some other one, you still wouldn't necessarily be able to utilize that information in any way.
As such, it's only important for the compiler to know what the class inherits from once it learns its full definition.
After clarification in comments: if you want to prevent instantiation of a class template with some types, its definition is the place to do it. A simple static_assert inside the class body will do the trick; Boost.StaticAssert or older SFINAE tricks will do the job for pre-C++11 code.
If you are happy with delaying the error to link-time, rather than compile time, you can declare all the member functions of parent in parent.h, provide definitions in parent.cpp, and explicitly instantiate the finite list of classes that you want.
Parent.h
template<typename T>
class ParentClass : public GrandparentClass<T>
{
ParentClass();
};
class ParentClass<int>;
class ParentClass<long int>; // or whatever
Parent.cpp
template <typename T>
ParentClass::ParentClass() : grandparentMember(5) {}
Hope this is not duplicated, but wasn't able to find an elegant solution. Is it possible to say that subclasses of a special base class can only created in a template factory function? Because of simplicity I only want to force this behavior in the base class. Here is an simple example:
template <class T>
T* createBase();
template<typename T>
class Base {
protected:
template <class T>
friend T* createBase();
static T* create()
{
return new T();
}
};
class TestClass1 : public Base<TestClass1>
{
public:
TestClass1() : Base() {}
};
template <class T>
T* createBase()
{
static_assert(std::is_base_of<Base<T>, T>::value, "use the createBase function only for Base<T> subclasses");
return Base<T>::create();
}
Actually this is allowed:
TestClass2 *testClass = createBase<TestClass2>();
TestClass2 tester;
But I only want to have this:
TestClass1 *testClass = createBase<TestClass1>(); //allowed
TestClass1 tester; // compile error
For sure I know I only have to put the constructor of TestClass1 private or protected. But it would be really nice to say that in the Base object.
Edit:
An compile error when the constructor of the subclass is public would be a also a nice solution. Maybe with a static_assert().
You can't control the accessibility of a constructor from the base class, even with CRTP.
What you can do is add a static_assert in the base ctor checking that the T a.k.a the derived class has no publicly accessible default ctor:
template <class T>
class Base {
public:
Base() {
static_assert(!std::is_default_constructible<T>::value,
"T must not be default constructible");
}
};
the static_asswert doesn't work on class scope for reasons showned here: CRTP std::is_default_constructible not working as expected
In Java, there is a detailed generic class hierarchy for containers. Java defines interfaces like ICollection<T> which is inherited by ISet<T> which is inherited by IList<T> and implemented by ArrayList<T>. I would like to create a similar hierarchy in a C++ library I am creating.
Using C++ templates however, makes this very cumbersome. For example, say I define an ISet<T>:
template<typename T>
class ISet
{
public:
virtual ~ISet() = 0;
virtual void add(T e) = 0;
virtual size_t size() = 0;
virtual bool isEmpty()
{
return size() == 0;
}
};
Then, if I wanted to make a List<T> which implements ISet<T>, I would have to list in the class definition every method that I wanted to inherit but not override, in order to let me later call it without something messy like alist::ISet<T>->isEmpty():
template<typename T>
class List : public ISet<T>
{
public:
...
void add(T e)
{
...
}
virtual sz size()
{
...
}
using ISet<T>::isEmpty; //well this is annoying
};
I understand the reason for this, and "why doesn't this work the way I expect it to?" has been answered in these qeustions: here and here.
My question is, is there a clean (or even any!) way to achieve this without having to explicitly list every inherited but not overridden method in the base class?
What I would really like would be something I could put in List<T> like:
using ISet<T>::*;
which would make all of the methods in ISet<T> dependent in the class definition of List<T>, and would alias them to List<T>::functionName.
Please tell me there is SOME way to achieve this without having to update every inheriting class's list of using directives each time I change one of my templated interfaces!
Do I have to resort to a preprocessor define of using directives defined along with the interface? Arrrrgghhhh!
This statement is incorrect:
... would have to list in the class definition every method that I
wanted to inherit but not override, in order to let me later call it
without something messy like alist::ISet->isEmpty():
Try to compile following code:
template<class T>
class Base {
public:
virtual void f1();
virtual void f2();
};
template<class T>
class Derived : public Base<T> {
public:
virtual void f1();
};
void foobar()
{
Derived<int> d;
d.f1();
d.f2();
}
If you mean that you want to access base class methods or members on derived class, you can simply do that more explicit way:
template<class T>
class Derived : public Base<T> {
public:
virtual void f1() { this->f2(); }
};
That is not messy and works as you asked, just little bit more explicit (some says it is good idea to always use this-> explicitly).
I realize how many times this have been talked about but I have not found an appropriate solution for my problem. I have just implemented a Meyer's singleton class into my project but I would like to make a template out of it so that I can use it as e.g.
class Game : public Singleton<Game>
{ /* stuff */
}
And I have my class defined like this
template <typename T>
class Singleton
{
public:
static T& Instance();
private:
Singleton();
//declare them to prevent copies
Singleton(Singleton const&);
void operator=(Singleton const&);
};// END OF CLASS DEFINITION
// METHODS' DEFINITIONS
template<typename T>
T& Singleton<T>::Instance()
{
static T _instance;
return _instance;
}
Allowing ctor to be public will destroy whole vision of Singletons.
EDIT
Ok, so I have updated my Game class to befriend Singleton<Game>
class Game : public Singleton<Game>
{
friend class Singleton<Game>;
//...
}
But now I have something like:
undefined reference to 'Singleton< Game >::Singleton()'
in function Game::Game() which is empty
Allowing ctor to be public will destroy whole vision of Singletons.
No, not really. Game should have a private constructor. Constructor of Singleton is irrelevant. An instance of Singleton<Game> will not help anyone to get another instance of Game, which is what you're interested in.
Anyway, you can declare the constructor protected. Alternatively, you can keep the constructor private and befriend the template parameter. Except this does not work in C++03. Should work in C++11 though. But there's a little trick:
template <typename T>
struct wrapper
{
typedef T type;
};
template <typename T>
class Singleton
{
friend class wrapper<T>::type;
Update: Game should befriend Singleton<Game>, or at least Singleton<Game>::Instance, to allow its constructor to be called.
ctor Singleton() -> protected?
template <class T>
class baseclass{
protected:
T data;
public:
baseclass(){};
void setData(T d);
};
template<class T>
void baseclass<T>::setT(T d){
data = d;
}
Shown above is my base class, one protected member variable, one setter.
template <class T>
class aclass : public baseclass<T>
{
public:
aclass(T d);
};
template<class T>
aclass<T>::aclass(T d){
setData(d); <---WORKS
data = d; <---DOESN'T WORK
}
Now this is my subclass of the first. For some reason, accessing the protected member variable directly is not working though I believe it ought to. However, accessing the setter works fine. I'm a noob with C++, I'm sure I'm missing something obvious.
The reason that this doesn't work is a quirk in the way that C++ templates do name resolution. In particular, if you have a template class that inherits from another class that depends on a template type (as you're doing in this case), you cannot access the members of that base class directly without giving the compiler a hint about where to look. This is the cause of the error you're getting.
To fix this, you can rewrite your constructor as
template<class T>
aclass<T>::aclass(T d){
setData(d);
this->data = d;
}
Now that the compiler knows that data must somehow be a member of aclass<T>, it can find what it's looking for.
Interestingly, you should also be getting an error on the previous line for the same reason. I'm not sure why it decided to compile. To fix this, you can either do this:
template<class T>
aclass<T>::aclass(T d){
this->setData(d);
this->data = d;
}
Alternatively, you can add a using declaration to tell the compiler that aclass inherits the setData method from its parent class. In the class declaration, consider adding this line:
template <class T>
class aclass : public baseclass<T>
{
public:
aclass(T d);
using baseclass<T>::setData;
};
Like the this-> for data members, this trick makes it unambiguous where the name setData comes from and helps the compiler know what you're talking about.
Hope this helps!