I have such class
template<typename T>
class ConnectionStatus:
{
public:
virtual void setStatus(const T& status) = 0;
virtual T getStatus() = 0;
};
And i want to have a reference to this class in another class, so i do this: ConnectionStatus<typename T>& status; but compiler said error: template argument 1 is invalid. So how i can make a refernce to template virtual class?
Thank you for any help.
There are two main possibilities: when you know what that template argument should be for your class and when you don't.
For the former, it's a simple case of providing it (say it's int in this case):
struct MyClass
{
ConnectionStatus<int> &m_connection_status;
};
If you don't know the argument, make your class a template class:
template <typename ConnectionStatusType>
struct MyClass
{
ConnectionStatus<ConnectionStatusType> &m_connection_status;
};
Related
I have an inheritance scheme that looks like this:
template <typename CollectionType>
class Sorter {
public:
virtual void sort(CollectionType &collection) = 0;
};
template <typename ElementType>
class VectorSorter : public Sorter<vector<ElementType>> {
...
};
Then, I'm adding a fully implemented class that goes like this:
template <typename T>
class VectorInsertionSorter : public VectorSorter<T> {
public:
void sort(vector<T> &collection) {
...
}
}
I create a fully specialized VectorInsertionSorter<int> through a factory class that is supposed to return a reference to a VectorSorter<int>.
This makes it impossible to call the
VectorInsertionSorter<int>::sort(vector<int> &collection) method, which I thought would be dynamically dispatched over Sorter::sort(CollectionType &collection).
Is it possible to provide a method implementation for templated parameters like above, or if I'm doing it wrong how can it be achieved?
I can't seem to call a method of a base class without scoping to the base class, and it seems that this is because I have overloaded the method. If I do not overload the method then the compiler doesn't complain. Here's an example of what I'd like to do:
struct BaseClass {
template <typename T> T& foo(T& t) {
return t;
}
};
class ChildClass: public BaseClass {
public:
// The presence of this template causes compiler confusion
template <class T> T& foo(T& t, int szl) {
return t;
}
template <class T> int bar(T& t) {
// But if I scope this as BaseClass::foo(...) it's all good
return foo(t);
}
};
int main() {
int t = 1;
ChildClass c;
c.bar(t);
}
If in bar(...) I call BaseClass::foo(...) the compiler does not complain, but I don't see any ambiguity here and so I'm confused as to why I'd need to do this.
When the compiler tries to match a function name with a function, it does so in two steps. In the first step it finds all the functions that match the given name. If it finds more than one function, it tries the logic of overload resolution to find the best matching function.
In the first step, if the compiler finds a name in the class, it stops looking for functions of the same name in base classes. In your case, since it finds a foo in ChildClass, it stops searching for functions named foo in BaseClass. However, the only matching foo does not match the call and the compiler reports an error.
How to resolve the problem:
Use the method you described in your post. Call BaseClass::foo(...).
Bring all the foo from BaseClass into the scope of ChildClass.
class ChildClass: public BaseClass {
public:
using BaseClass::foo;
template <class T> T& foo(int baz, T& t, int szl) {
return t;
}
template <class T> int bar(T& t) {
return sizeof(foo(1, t)); // Should work.
}
};
From the C++ standard 3.3.10 paragraph 1 :
A name can be hidden by an explicit declaration of that same name in
a nested declarative region or derived class
ChildClass::foo shadows the definition of BaseClass::foo. All you need to bring it into scope is a using directive:
class ChildClass: public BaseClass {
public:
using BaseClass::foo;
template <class T> T& foo(int baz, T& t, int szl);
};
You need a using, like:
using BaseClass::foo;
I want to do:
template <class Derived=BattleData>
class BattleData : public BattleCommandManager<Derived> {
};
But obviously BattleData isn't declared, so I tried a forward declaration:
template <class T> class BattleData;
template <class Derived=BattleData>
class BattleData : public BattleCommandManager<Derived> {
};
But then I get
error: "wrong number of template parameter on the second line, with
BattleData.
I really fail to see a solution to this!
Edit:
The reason I'm doing this is because I want to be able to use BattleData directly as a class, but I also want to be able to subclass it in which case I have to specify the derived class as the second template parameter.
For example let's say the corpus of my BattleData class is :
template <class Derived> class BattleData: public BaseClass<Derived> {
void foo1(){};
void foo2(){};
void foo3(){};
}
And I have a subclass
template class SubBattleData: public BattleData<SubBattleData> {
void foo1(){};
}
I would still want, in some cases, to be able to write code like this:
BattleData *x = new BattleData(...);
I can't even do the following without being able to use default arguments:
BattleData<BattleData> *x = new BattleData<BattleData>(...);
On one side, the reason functions aren't virtualized in the BattleData class is the benefit of having no virtual function. The other reason it doesn't work for me is that one of the parent CRTP classes invokes functions only if they're present in the derived type (using decltype(Derived::function) and enable-if like structures), and fall back to default behavior otherwise. Since there can be a great deal of those functions with a particular design pattern (like a CRTP that reads a protocol with many different cases and processes a case a particular way only if the derived class specify the corresponding function, otherwise just transfer it without processing).
So those functions can be present in SubBattleData and not BattleData, but both classes would work fine if instantiated, yet it's impossible to instantiate BattleData.
You should be able to accomplish your original design goals more naturally than the above. You can't use the actual Derived typename as the default clearly because what you're really trying to write is the following:
template <class Derived=BattleData <BattleData <BattleData <...>>>
class BattleData : public BattleCommandManager<Derived> {
};
You get the idea. Instead, just use a placeholder like void:
template <typename T = void>
class BattleData : public BattleCommandManager <
typename std::conditional <
std::is_same <T, void>::value,
BattleData <void>,
T
>::type>
{
};
Disclaimer: I did not compile the above.
Can't you use an Empty class for the second template parameter?
template <class T=DataContainer, class Derived=BattleData<T, Empty> >
class BattleData : public BattleCommandManager<Derived> {
};
I don't see what you are trying to do. What is wrong with
template <class T=DataContainer>
class BattleData : public BattleCommandManager< BattleData<T> > {
};
If you specify Derived to be something else than the actual derived class static polymorphism is not going to work and CRTP becomes somewhat useless anyway.
Edit: From what I have gathered this is what you want to in abstract terms:
template <class Derived>
struct Base {
void interface() {
static_cast<Derived*>(this)->implementation();
}
};
template<typename T>
struct Derived : Base<Derived> {
// dummy so we get you example
T t;
void implementation() {
std::cout << "derived" << std::endl;
}
};
struct Derived2 : public Derived<int> {
// hide implementation in Derived
// but still have Base::interface make the right call statically
void implementation() {
std::cout << "derived2" << std::endl;
}
};
There is no way I know of that you can make this work. Another
approach would be to use policy classes instead of CRTP. They are
compatible with inheritance and you can achieve similar behaviour.
template<typename Policy>
struct BattleCmdManager : public Policy {
using Policy::foo;
};
template<typename T>
struct BattleData {
// ...
protected:
void foo();
};
struct BattleData2 : public BattleData<int {
// ...
protected:
void foo();
};
Here is how I solved it:
template <class Derived> class BattleDataInh: public BaseClass<Derived> {
void foo1(){};
void foo2(){};
void foo3(){};
};
template class SubBattleData: public BattleDataInh<SubBattleData> {
void foo1(){};
};
class BattleData : public BattleDataInh<BattleData> {
};
And that way, I can add any other template parameters too. The solution was in front of my eyes the whole time but I didn't see it...
I'm wanting to invoke a specialized templated function by using a pointer to it's base type. I'm not sure if this possible so I'm open to suggestions and/or alternatives. Here is an example of my situation:
class CBase {};
class CDerivedClass : public CBase {};
template<class T>
int func<T>(T &x) { ... };
template<>
int func<CDerivedClass>(CDerivedClass &x) { ... };
I have another function that manages a list of CBase pointers and then calls the func() function.
void doStuff()
{
CBase *foo[10] = { ...... };
for (int i = 0; i < 10; ++i)
func(*foo[i]);
}
Is there a way to get the derived type, so that func(CDerivedClass &) is called?
What about Template Subclassing? This idiom allows you to use compile-time polymorphism in C++. The cost of it is higher verbosity (such as specifying the whole class hierarchy up to the current class). In your case:
template <typename TSpec> class Klass {};
template <typename TSpec> struct SpecTag {};
template <typename TSpec> class Klass<SpecTag<TSpec> > {};
template <typename TSpec>
int func(Klass<TSpec> &x) { ... };
template <typename TSpec>
int func(Klass<SpecTag<TSpec> > &x) { ... };
The "Visitor" pattern comes to the rescue in this case. It enables polymorphic behavior in an algorithm implemented outside the class. Some support code is required inside the class, but new algorithms can later be added, existing algorithms modified, etc., without affecting the class.
Alternative solution : from your example, it's obvious that you just should to use a virtual method in CBase, so you just have to define a virtual function in CBase and an overriding function in the derived class.
I have a templated class named check and its partial specialization, now i am publically inheriting a class named childcheck from the partial specialization of the class check. but compiler gives following error message
no matching function for call to `check::check()'
candidates are: check::check(const check&)
check::check(t*) [with t = int*]
look at the code and explain the reason please
#include<iostream.h>
template<class t>
class check
{
t object;
public:
check(t);
};
//defining the constructor
template<class t>
check<t>::check<t>(t element)
{
cout<<"general templated class constructor"<<endl;
}
//partial specialization
template<class t>
class check<t*>
{
t* object;
public:
check(t*);
};
template<class t>
check<t*>::check<t*>(t* element)
{
cout<<"partial specialization constructor"<<endl;
}
//childcheck class which is derived from the partial specialization
template<class t>
class childcheck:public check<t*>//inheriting from the partial specialization
{
t object;
public:
childcheck(t);
};
template<class t>
childcheck<t>::childcheck<t>(t element):check<t>(element)
{
cout<<"child class constructor"<<endl;
}
main()
{
int x=2;
int*ptr=&x;
childcheck<int*>object(ptr);
cout<<endl;
system("pause");
}
You inherit from check<t*> yet call a base class constructor check<t> as if you inherited from check<t>. Which check<> do you want to inherit from?
I believe that what you really want do is this:
template<class t>
class childcheck:public check<t>
If t is int*, then childcheck<int*> will inherit from check<int*> which is fine. The rest of your code can remain the way it is in the original question.
Read about Template Partial Specialization at cprogramming.com, it explains
your previous question.