C++ - Template subclass inherits from multiple template classes - c++

I am creating a simple class named HashMap:
template <typename K,typename V> class HashMap{
.
.
.
public:
class Hashable;
I created another class:
template<typename T> class Stack;
Now I must create a new class (NewStackClass), which extends Stack and HashMap<K,V>::Hashable.
Objects of this class are meant to be instantiated when K=Stack/NewStackClass.
Example:
HashMap<NewStackClass<int>,int> map;
//T=int;K=NewStackClass<int>;V=int;
or:
HashMap<Stack<char>,int> map;
//T=char;K=Stack<char>;V=int;
How can I obtain this? Also, I want to split class declaration from its implementation.
I already tried with this:
template <typename B, typename C>
template <typename A> class NewStackClass : public Stack<A>, public HashMap<B,C>::Hashable{
virtual int hashCode() const;
bool operator==(const MyStack<A>& stack);
};
but it didn't work:
[Error] too many template-parameter-lists
Any help is appreciated.
EDIT
Creating NewStackclass:
template <typename StackType,typename HashMapValue> class MyStack : public NewStackClass<StackType>, public HashMap<Stack<StackType>,HashMapValue>::Hashable{
virtual int hashCode() const {
return 1;
}
bool operator==(const NewStackClass<StackType,HashMapValue>& stack){
return true;
}
};
Let's get in the private area of HashMap class:
private:
int hash(const Hashable& key) const{
return (31*17 +key.hashCode()) % TABLE_SIZE;
}
Doing this in main.cpp:
HashMap<NewStackClass<int,int>,int> map1;
NewStackClass<int,int> stack;
map1.put(stack,0);
Brings out this error:
[Error] no matching function for call to "HashMap<NewStackClass<int, int>, int>::hash(const NewStackClass<int, int>&)"
Error comes from this:
[Note] no known conversion for argument 1 from 'const NewStackClass' to 'const HashMap, int>::Hashable&'

Your code contains a syntactical flaw. You may only have a single template parameter list for your class.
merge
template <typename B, typename C>
template <typename A> class NewStackClass ...
to this
template <typename B, typename C, typename A>
class NewStackClass ...
to make it compile.
Also you did not provide information on what MyStack is supposed to be. I just assume that you meant to write Stack instead.
You should also think about whether your class NewStackClass really needs three template arguments or if there are actually only two distinct ones.
Judging by your question, your might want to do:
template <typename K, typename V>
class NewStackClass : public Stack<K>, public HashMap<Stack<K>,V>::Hashable {
instead.
Fixed Code (Syntax Only)
template <typename K,typename V>
class HashMap {
public:
class Hashable {
};
};
template<typename T> class Stack {
};
template <typename B, typename C, typename A>
class NewStackClass : public Stack<A>, public HashMap<B,C>::Hashable {
virtual int hashCode() const;
bool operator==(const Stack<A>& stack);
};

Related

Is there an alternative to overloading or template specialization? I am attempting to call a specific function based on a template parameter

I have generated a simpler example of what I am trying to accomplish. I would like to be able to call a function, which returns a class containing two template parameters, based on one of the two templated parameters (Variance).
My hierarchy can be simplified to this.
template<typename T>
class AbstractType {};
template<typename T, Variance Type>
class BaseType : public AbstractType<T> {};
template<typename T, Variance Type>
class FinalType : public BaseType<T, Type>{};
Where FinalType in this example isn't strictly necessary, it also inherits from other templated classes in my actual code, which serves no purpose in this example, so it's been removed.
Here's the example code.
enum class Variance {
Interval,
Weighted,
Constant
};
template<typename T>
class AbstractType
{
protected:
AbstractType(T* _Instance) :
Instance(_Instance) {};
T* Instance;
};
template<typename T, Variance Type>
class BaseType : public AbstractType<T>
{
protected:
BaseType(T* _Instance) :
AbstractType<T>(_Instance) {};
};
template<typename T>
class BaseType<T, Variance::Interval> : public AbstractType<T>
{
protected:
BaseType(T* _Instance) :
AbstractType<T>(_Instance) {};
int Interval;
public:
void SetInterval(int NewInterval) { Interval = NewInterval; }
};
template<typename T>
class BaseType<T, Variance::Weighted> : public AbstractType<T>
{
protected:
BaseType(T* _Instance) :
AbstractType<T>(_Instance) {};
int Weight;
public:
void SetWeight(int NewWeight) { Weight = NewWeight; }
};
template<typename T, Variance Type>
class FinalType : public BaseType<T, Type>
{
public:
FinalType(T* _Instance) :
BaseType<T, Type>(_Instance)
{};
};
struct Interface
{
template<typename T>
BaseType<T, Variance::Weighted>* CreateBaseInstance(T t, int Weight) {
FinalType<T, Variance::Weighted>* OutObj = new FinalType<T, Variance::Weighted>(t);
OutObj.SetWeight(Weight);
return OutObj;
}
template<typename T>
BaseType <T, Variance::Interval>* CreateBaseInstance(T t, int Interval) {
FinalType<T, Variance::Weighted>* OutObj = new FinalType<T, Variance::Interval>(t);
OutObj.SetInterval(20);
return OutObj;
}
};
struct Object {};
void test()
{
Interface Inter;
Object Obj;
Inter.CreateBaseInstance<Object, Variance::Weighted>(Obj, 50); // Too many template arguments
Inter.CreateBaseInstance<Object, Variance::Interval>(Obj, 10); // Too many template arguments
Inter.CreateBaseInstance<Object>(Obj, 50); // More than one instance of overloaded function
Inter.CreateBaseInstance<Object>(Obj, 10); // More than one instance of overloaded function
}
Additionally, Object being used as the first template is just for testing purposes. I will not know the type in this codebase.
I've been able to resolve this problem by creating multiple functions such as..
template<typename T>
BaseType<T, Variance::Interval>* CreateIntervalInstance(T t, int Interval)…
template<typename T>
BaseType<T, Variance::Weighted>* CreateWeightedInstance(T t, int Weight)…
template<typename T>
BaseType<T, Variance::Constant>* CreateConstantInstance(T t)…
However, as mentioned earlier, FinalType inherits from another set of classes, so while the above works, it becomes crowded and unsustainable with the number of functions needed to do the simple tasks above.
I have experimented with making the Interface have a template parameter, such as..
// Base Class
template<Variance Variant>
class Interface…
// Specialized
template<>
class Interface<Variance::Interval>…
// Functions to create Interval Instances
//Specialized
template<>
class Interface<Variance::Weighted>…
// Functions to create Weighted Instances
But, I once again run into it becoming unsustainable.
The last thing I am currently looking into is Type Traits, but am unsure if or how that could be implemented to make this simpler.
Without following all of it really in detail, don't you just want e.g.
template<typename T, Variance Type>
auto CreateBaseInstance(T t, int value) {
// Instead of `auto` maybe `std::unique_ptr<BaseType<T, Type>>`
auto OutObj = std::make_unique<FinalType<T, Type>>(t);
if constexpr(Type == Variance::Weighted) {
OutObj->SetWeight(value);
} else if constexpr(Type == Variance::Interval) {
OutObj->SetInterval(value);
}
return OutObj;
}
(I replaced new with std::make_unique, because using raw new like this is generally considered bad practice due to the memory management problems it causes.)

Best approach to declare as friend a class template without knowing one its template arguments

I stumbled into a scenario and I'm trying to figure out for the cleanest approach, if there's any.
I have a template class with a protected constructor, that needs to be instantiated by a friend template class. Both share part of template parameters, but not all. Here's a example of my problem.
I wish to know from experienced programmers if there are other possible solutions (I suppose not, besides turning constructor public), and if between the two I present one its more acceptable than the other.
Thanks
Solution 1- I supply "unnecessary" template parameters to the class with protected constructor (class Element).
template <typename Tp_>
class Engine_Type_X
{
};
template <typename Tp_>
class Engine_Type_Z
{
};
//Forward declaration
template <typename Tp_, template<typename> typename Eng_>
class Container;
//Eng_ is only required to declare the friend class
template <typename Tp_,template<typename> typename Eng_>
class Element
{
friend class Container<Tp_,Eng_>;
Tp_ tp_;
protected:
Element(Tp_ tp) : tp_{tp} //protected ctor!!!
{}
};
template <typename Tp_, template<typename> typename Eng_>
class Container
{
using Element_tp = Element<Tp_,Eng_>;
using Engine_tp = Eng_<Tp_>;
std::vector<Element_tp> container_;
Engine_tp &engine_;
public:
Container(Engine_tp &engine) : container_{},engine_{engine}
{}
void install(Tp_ tp)
{ Element_tp elem{tp};
container_.emplace_back(elem);
}
};
Solution 2 - I use an approach like the one I've found here How to declare a templated struct/class as a friend?
template <typename Tp_>
class Engine_Type_X
{
};
template <typename Tp_>
class Engine_Type_Z
{
};
template <typename Tp_>
class Element
{
template<typename,template<typename>typename> friend class Container; //All templated classes are friend
Tp_ tp_;
protected:
Element(Tp_ tp) : tp_{tp} //protected ctor!!!
{}
};
template <typename Tp_, template<typename> typename Eng_>
class Container
{
using Element_tp = Element<Tp_>;
using Engine_tp = Eng_<Tp_>;
std::vector<Element_tp> container_;
Engine_tp &engine_;
public:
Container(Engine_tp &engine) : container_{},engine_{engine}
{}
void install(Tp_ tp)
{ Element_tp elem{tp};
container_.emplace_back(elem);
}
};
You still have some options to explore.
You could make one class an inner class (called nested class), that would automaticly
friend it to the 'outside' class. See https://en.cppreference.com/w/cpp/language/nested_types
Another approach is to require a so called 'token' as a parameter to a
the constructor, this token type doesn't usually take template parameters, then make it so that this token can only be
created by the other class (could be a nested type or friended).
On request from OP, here is an outline of one way to accomplish 2. option: (using c++0x)
template<typename Test, template<typename...> class Ref>
struct is_specialization : std::false_type {};
template<template<typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref>: std::true_type {};
template <class T>
class create_token {
public:
typedef T Type;
//copy of token not allowed !
create_token(const create_token &) = delete;
create_token& operator=(const create_token &) = delete;
//move is fine
create_token(create_token &&) = default;
create_token& operator=(create_token &&) = default;
friend class T;
private:
create_token();
};
template<class BlaBlaBla>
struct Element {
template<class T>
Element(create_token<T> t) {
static_assert(std::is_specialization<create_token<T>::Type, Container>::value, "Wrong type of token provided");
}
};
template<class Whatever>
struct Container {
template<class T>
Element(create_token<T> t) {
static_assert(std::is_specialization<create_token<T>::Type, Element>::value, "Wrong type of token provided");
}
};

How do I specialize this template member function?

I have this setup:
class DontUse;
template<class T,class U = DontUse, class V = SomeStandardType>
class Foo
{
public:
void bar(U &uh);
};
When U is set to DontUse, I want bar to be an empty function. In all other cases, I want bar to have some implementation. I tried doing this using specialization, but this code (which I realize is somehow incorrect) doesn't compile:
template<class T,class V> void Foo<T,DontUse,V>::bar(DontUse &none){}
template<class T,class U,class V> void Foo<T,U,V>::bar(U &uh)
{
//do something here
}
The error message is this (MSVC10):
1>path_to_project: error C2244: 'Foo<T,U,V>::bar' : unable to match function definition to an existing declaration
and it points to the line of the first template specialization.
How do I do this correctly?
Here's the actual code, although it's reduced to the minimalist part that's relevant:
struct DontUse;
template<typename Derived, typename Renderer = DontUse, typename TimeType = long>
class Gamestate
{
public:
void Render(Renderer &r);
};
template<typename Derived, typename TimeType> void Gamestate<Derived, DontUse,TimeType>::Render( DontUse){}
template<typename Derived, typename Renderer, typename TimeType> void Gamestate<Derived,Renderer,TimeType>::Render(Renderer &r)
{
static_cast<Derived*>(this)->Render(r);
}
You cannot specialize individual members of a template. You have to specialize the class itself:
class DontUse;
template<class T, class V>
class Foo<T, DontUse, V>
{
   public:
     void bar(DontUse)
{ }
};
I recommend to just use this:
#include <type_traits>
template <class A, class B, class C>
struct S
{
void foo(B& b)
{
static_assert(!std::is_same<U, DontUse>::value, "Bad Boy!");
}
};
Or, if you really want a empty function, just use an if.
#include <type_traits>
template <class A, class B, class C>
struct S
{
void foo(B& b)
{
if(!std::is_same<U, DontUse>::value)
{
//all code goes here
}
}
};
It doesn't work like that. A member function of a class template is not itself a separate template, and cannot be specialized (partially or fully) independently of the class template.
You need to define a partial specialization of the class template Foo, give it a bar member function, and define that.

compiler stack overflow on template code

While working on my own type erasure iterator, I ran into an issue where the compiler (MSVC10) crashed with a stack overflow on this code:
struct base {}; //In actual code, this is a template struct that holds data
template<class category, class valuetype>
struct any; //In actual code, this is abstract base struct
template<class basetype, class category, class valuetype>
struct from; //In actual code, this is function definitions of any
template<class valuetype>
struct any<void,valuetype>
{ void a() {} };
template<class category, class valuetype>
struct any
: public any<void,valuetype> //commenting this line makes it compile
{ void b() {} };
template<class basetype, class valuetype>
struct from<basetype,void,valuetype>
: public base //commenting out _either_ of these makes it compile
, public any<void,valuetype>
{ void c() {} };
int main() {
from<int, void, char> a;
a.a();
a.c();
any<int, char> b;
b.a();
b.b();
return 0;
}
Obviously, I've removed everything I can where the bug remains. (Origional code was 780+ lines) Removing any remaining template parameters causes the code to compile.
The full error message is:
main.cpp(23): fatal error C1063: compiler limit : compiler stack overflow
main.cpp(20) : see reference to class template instantiation 'from<basetype,void,valuetype>' being compiled
IDEOne compiles it fine. I've heard that MSVC implemented two-phase lookup wrong, which seems relevant, but doesn't explain why it compiles when I remove the line that makes from inherit from base. Can anyone teach me why MSVC10 won't compile this? What did I do that I should be avoiding?
As a workaround, consider introducing an additional class between the unspecialized any and the specialization with category = void:
template <class valuetype>
class detail_void_any
: public any<void, valuetype>
{
};
template<class category, class valuetype>
class any
: public detail_void_any<valuetype>
{
};
The following complete program should compile without error:
class base {}; // Data Holder (in reality it's templated, so required)
template<class category, class valuetype>
class any; // Virtual Function Interface
template<class basetype, class category, class valuetype>
class from; // Virtual Function Implementation
template<class valuetype>
class any<void,valuetype>
{};
template <class valuetype>
class detail_void_any
: public any<void, valuetype>
{
};
template<class category, class valuetype>
class any
: public detail_void_any<valuetype>
{
};
template<class basetype, class valuetype>
class from<basetype,void,valuetype>
: public base //commenting out _either_ of these makes it compile
, public any<void,valuetype>
{}; //this is line 23, where the compiler crashes
int main() {return 0;}
Well I give up but I did manage to generate a warning:
template <typename T1, typename T2>
class Any; // forward
template <typename T2>
class Any<void, T2> // partial spec of forward
{};
template <typename T1, typename T2>
class Any: // template definition
public Any<void, T2> // inherit from partial spec
{};
template <typename T1, typename T2>
class From :
public Any<int, T2>, // inherit definition
public Any<void, T2> // inherit definition or partial spec?
// with spec first we get fatal error C1063: compiler limit : compiler stack overflow (CRASH!)
// with definition first we get warning C4584: 'From<T1,T2>' : base-class 'Any<void,T2>' is already a base-class of 'Any<int,T2>'
{};
int main()
{
return 0;
}
Simplest workaround: Replace:
template<class category, class valuetype>
class any : public any<void, valuetype>
{
};
with:
template<class valuetype, class category>
class any : public any<void, valuetype>
{
};

How do we typedef or redefine a templated nested class in the subclass?

Consider the following:
template <typename T>
class Base {
public:
template <typename U>
class Nested { };
};
template <typename T>
class Derived : public Base<T> {
public:
//How do we typedef of redefine Base<T>::Nested?
using Base<T>::Nested; //This does not work
using Base<T>::template<typename U> Nested; //Cannot do this either
typedef typename Base<T>::template<typename U> Nested Nested; //Nope..
//now we want to use the Nested class here
template <typename U>
Class NestedDerived : public Nested { };
//or like this:
Nested<int> nestedVar; // obviously does not work
};
How to use the templated Nested class in the Derived class? Is this possible to do in current version of C++ standard?
Actually using works as advertised, it just doesn't get rid of the dependent-name issue in the template and it can't currently alias templates directly (will be fixed in C++0x):
template <class T>
struct Base {
template <class U> struct Nested {};
};
template <class T>
struct Derived : Base<T> {
using Base<T>::Nested;
// need to prefix Nested with template because
// it is a dependent template:
struct X : Base<T>::template Nested<int> {};
// same here:
template<class U>
struct Y : Base<T>::template Nested<U> {};
// data member, typename is needed here:
typename Base<T>::template Nested<int> data;
};
void f() {
Derived<int>::Nested<int> n; // works fine outside
}
There is another possible gotcha when using Derived<T>::Nested in templates, but again that is a dependent-name issue, not inheritance-related:
template<class T>
void g() {
// Nested is a dependent type and a dependent template, thus
// we need 'typename' and 'template':
typedef typename Derived<T>::template Nested<int> NestedInt;
}
Just remember that names that depend on template arguments have to be
prefixed with typename if its a dependent type: typename A<T>::B
directly prefixed with template if its a dependent template: A<T>::template f<int>()
both if both: typename A<T>::template B<int>
typename is illegal in base-class-lists: template<class T> struct A : B<T>, C<T>::template D<int> {};
This seems to work:
(EDIT: added some more lines to show the first template statement. And thanks to Samir Talwar for correcting my formatting!)
template <typename T, typename U>
class Derived : public Base<T> {
public:
typedef typename Base<T>::template Nested<U> Nested;
class NestedDerived : public Nested { };
Nested nestedVar;
};
Try this:
template <typename T>
class Base {
public:
template <typename U>
class Nested { };
};
template <typename T>
class Derived : public Base<T> {
public:
//How do we typedef of redefine Base<T>::Nested?
//using Base<T>::Nested; //This does not work
//using Base<T>::template<typename U> Nested; //Cannot do this either
//typedef typename Base<T>::template<typename U> Nested Nested; //Nope..
//now we want to use the Nested class here
template <typename U>
class NestedDerived : public Base<T>::template Nested<U> { };
};
int main()
{
Base<int>::Nested<double> nested;
Derived<int>::NestedDerived<double> nested_derived;
return 0;
}
Compiled fine using gcc 4.3.3 on slackware 13
I'm still not 100% sure what you want, but you could try.
This compiled on Visual Studio
template <typename T>
class Base {
public:
template <typename U>
class Nested { };
};
template <typename T>
class Derived : public Base<T> {
public:
//now we want to use the Nested class here
template <typename U>
class NestedDerived : public Nested<U> { };
};
int _tmain(int argc, _TCHAR* argv[])
{
Base<int>::Nested<double> blah2;
Derived<int>::NestedDerived<int> blah;
return 0;
}