Template dependent typedefs - c++

I am modifying a templated A* search and now have the following class (part of):
template <typename TNode, typename THeuristic>
class AStar
{
public:
// Typedefs.
typedef d_ary_heap<TNode*, boost::heap::compare<NodeCompare<TNode>>, boost::heap::arity<4>, boost::heap::mutable_<true>> PriorityQueueType;
//...
}
Until now, I hadn't thought of templatizing the heuristic parameter, so the Node class was defined as follows:
template <typename T = float>
class Node
{
public:
// Typedefs:
typedef typename AStar<Node>::PriorityQueueType::handle_type HeapHandle;
//...
}
But now since AStar takes a second template paremeter for the heuristic the typedef gives a compile error here: typedef typename AStar<Node ??>.... Is it possible to make this work somehow while maintaining freedom to specify the heuristic in the AStar class?

You could factor your code differently and keep the heuristic-independent part separate:
namespace detail
{
template <typename T>
struct AStarHeap
{
using QueueType = /* ... */;
using HandleType = QueueType::handle_type;
// ...
};
}
template <typename Node, typename Heur>
struct AStar : detail::AStarHeap<Node>
{
// ...
};
template <typename T>
struct Node
{
using HeapHandle = typename detail::AStarHeap<T>::HandleType;
// ...
};

Reworking a bit from my comment on the question, here's how I would probably do it:
template <typename TNode, typename THeuristic = void>
class AStar;
template <typename TNode>
class AStar<TNode>
{
// put everything that does not depend on THeuristic here
};
template <typename TNode, typename THeuristic>
class AStar : public AStar<TNode>
{
// put everything that does depend on THeuristic here
};
Looking at it now, this takes much the same approach as Kerrek SB's answer, but has the advantage that your existing code, which uses AStar<TNode>, continues to compile so long as it does not attempt to do anything that requires THeuristic.

Related

Access templated "using" in templated parent class

I have a class hierarchy like this:
/* Base templated interface class */
template <class T>
class InterfaceClass {
public:
// Normal using sentence
using InnerType1 = SomeClass<T>;
// HERE1: Templated using sentence that I want to use in other places
template<typename SomeType>
using TplInnerType = SomeOtherClass<InnerType1, SomeType>;
};
/* Some templated intermediate class inheriting from the interface */
template <typename T>
class Class : InterfaceClass<T> {
public:
using BaseType = InterfaceClass<T>;
// This works
using typename BaseType::InnerType1;
// HERE2: This won't work in any form
using typename BaseType::TplInnerType;
};
/* Then I have some children using the CRTP as: */
class Child1 : Class<Child1> { ... };
class Child2 : Class<Child2> { ... };
I would like to use the templated using sentence (HERE1) from InterfaceClass in descendants (HERE2), but I cannot get the compiler (C++11 over clang 10) to resolve the type.
I have tried many combinations following compiler advice, including:
template <typename U> using typename BaseType::TplInnerType<U>;
template <typename U> using TplInnerType = BaseType::TplInnerType<U>;
template <typename U> using TplInnerType = typename BaseType::TplInnerType<U>;
template <typename U> using TplInnerType = BaseType::template TplInnerType<U>;
But suggestions drive my in a circle... Is what I try to do even possible?
Edit - another solution
Apart from #Jarod42 answer, which works for this toy example but not in my real case, I found another solution that works (sample):
template <typename T>
class Class : InterfaceClass<T> {
public:
using BaseType = InterfaceClass<T>;
using typename BaseType::InnerType1;
// This works
template <typename U>
using TplInnerType = typename BaseType::template TplInnerType<U>;
};
You should drop typename:
template <typename T>
class Class : public InterfaceClass<T> {
public:
using BaseType = InterfaceClass<T>;
using typename BaseType::InnerType1;
using BaseType::TplInnerType;
};
Demo

Nest template class method specialization [duplicate]

I'm trying to figure out the correct syntax for explicit specialization of a nested template class. The following code will better illustrate:
struct Column_Major;
struct Row_Major;
template<size_t rows, size_t cols, typename T, typename Allocator>
class Matrix
{
/* bunch of members */
template <typename storage = Column_Major>
class Iterator
{
/* bunch of members */
};
};
I'd like to write an explicit specialization for template <> class Matrix<...>::Iterator<Row_Major, but the syntax is eluding me. I have a suspicion that it is not possible to explicitly specialize the Iterator class without an explicit specialization of the containing class, Matrix. But I would be very happy if there is a way to do this.
I know I could make the Iterator class a separate class, not a member of the Matrix class, but having the classes nested as such allows me full access to the template parameters and datamebers of the Matrix class, which simplifies things. I know I could work around this if I need to, but I'd first like to investigate and understand the possibilities for the nested approach.
Thanks,
Shmuel
For explicit specialization, you need to specialize the outer class before the inner, you can see this question for example.
There is a workaround that is using partial specialization:
template<size_t rows, size_t cols, typename T, typename Allocator>
class Matrix
{
// Notice the additionnal dummy parameter
// vvvvvvvvvvvvv
template <typename storage = Column_Major, bool = true>
class Iterator
{
};
// Specialization
template <bool dummy>
class Iterator<Row_Major, dummy>
{
};
};
You can make Synxis answer (use of defaulted dummy parameter) even more clean with C++11:
/// template <typename X>, not needed for the example
struct Outer
{
private:
template <typename A, typename D = void>
struct Inner
{
Inner() { cout << "default" << endl; }
};
template <typename D>
struct Inner<int,D>
{
Inner() { cout << "int" << endl; }
};
public:
template <typename T>
using Nested = Inner<T>;
};
The advantage of this improvement is that the signature of Nested has only one template parameter, which I think will help if you want to match it correctly in template meta-programming.
I'm surprised the template parameter for the nested class isn't a parameter of the parent class instead.
The nested class can use the template parameters of the parent and this more closely ties the nested class to the parent. Your use of the word iterator suggests this is good, the iterator surely iterating over the same type the parent contains?
I'd do it like this:
template <class T>
class Outer
{
public:
class Inner
{
void Fn( T in )
{
}
};
};
// specialisation
void Outer<double>::Inner::Fn( double in )
{
}

C++ templates and union [duplicate]

I'm trying to figure out the correct syntax for explicit specialization of a nested template class. The following code will better illustrate:
struct Column_Major;
struct Row_Major;
template<size_t rows, size_t cols, typename T, typename Allocator>
class Matrix
{
/* bunch of members */
template <typename storage = Column_Major>
class Iterator
{
/* bunch of members */
};
};
I'd like to write an explicit specialization for template <> class Matrix<...>::Iterator<Row_Major, but the syntax is eluding me. I have a suspicion that it is not possible to explicitly specialize the Iterator class without an explicit specialization of the containing class, Matrix. But I would be very happy if there is a way to do this.
I know I could make the Iterator class a separate class, not a member of the Matrix class, but having the classes nested as such allows me full access to the template parameters and datamebers of the Matrix class, which simplifies things. I know I could work around this if I need to, but I'd first like to investigate and understand the possibilities for the nested approach.
Thanks,
Shmuel
For explicit specialization, you need to specialize the outer class before the inner, you can see this question for example.
There is a workaround that is using partial specialization:
template<size_t rows, size_t cols, typename T, typename Allocator>
class Matrix
{
// Notice the additionnal dummy parameter
// vvvvvvvvvvvvv
template <typename storage = Column_Major, bool = true>
class Iterator
{
};
// Specialization
template <bool dummy>
class Iterator<Row_Major, dummy>
{
};
};
You can make Synxis answer (use of defaulted dummy parameter) even more clean with C++11:
/// template <typename X>, not needed for the example
struct Outer
{
private:
template <typename A, typename D = void>
struct Inner
{
Inner() { cout << "default" << endl; }
};
template <typename D>
struct Inner<int,D>
{
Inner() { cout << "int" << endl; }
};
public:
template <typename T>
using Nested = Inner<T>;
};
The advantage of this improvement is that the signature of Nested has only one template parameter, which I think will help if you want to match it correctly in template meta-programming.
I'm surprised the template parameter for the nested class isn't a parameter of the parent class instead.
The nested class can use the template parameters of the parent and this more closely ties the nested class to the parent. Your use of the word iterator suggests this is good, the iterator surely iterating over the same type the parent contains?
I'd do it like this:
template <class T>
class Outer
{
public:
class Inner
{
void Fn( T in )
{
}
};
};
// specialisation
void Outer<double>::Inner::Fn( double in )
{
}

Need typename error (template related error)

I have a class called node inside another class which is templated. Some of the methods of class Node returns Node pointer. This is an excerpt of how I implemented
template <typename T>
class myClass{
....
class Node{
Node* getNodePointer();
...
}
}
...
template <typename T>
myClass<T>::Node* myClass<T>::Node::getNext()
{ return next; }
When I compile above code, I get this error " myClass.h:138:1: error: need ‘typename’ before ‘myClass::Node’ because ‘myClass’ is a dependent scope". How do I fix this problem? Many thanks
To clarify, the compiler has no idea that myClass<T>::Node is now or ever will be a type. Think of it this way:
template <typename T>
class A
{
public:
typedef T value_type;
};
template <typename T>
class B
{
public:
typename A<T>::value_type x;
};
template <> A<int> { public: static int value_type=10;}
You have to make the promise to the compiler that the type is a typename. It defaults to assuming that it is a value.
How do I fix this problem?
The compiler's error message s pretty clear about this point:
To use nested classes, structs or typedefinitions from a template class you need to add the typename keyword to tell the compiler you want to use it as a type:
template <typename T>
typename myClass<T>::Node* myClass<T>::Node::getNext() { // ...
// ^^^^^^^^ << Add typename keyword

Syntax for specialization of nested template class

I'm trying to figure out the correct syntax for explicit specialization of a nested template class. The following code will better illustrate:
struct Column_Major;
struct Row_Major;
template<size_t rows, size_t cols, typename T, typename Allocator>
class Matrix
{
/* bunch of members */
template <typename storage = Column_Major>
class Iterator
{
/* bunch of members */
};
};
I'd like to write an explicit specialization for template <> class Matrix<...>::Iterator<Row_Major, but the syntax is eluding me. I have a suspicion that it is not possible to explicitly specialize the Iterator class without an explicit specialization of the containing class, Matrix. But I would be very happy if there is a way to do this.
I know I could make the Iterator class a separate class, not a member of the Matrix class, but having the classes nested as such allows me full access to the template parameters and datamebers of the Matrix class, which simplifies things. I know I could work around this if I need to, but I'd first like to investigate and understand the possibilities for the nested approach.
Thanks,
Shmuel
For explicit specialization, you need to specialize the outer class before the inner, you can see this question for example.
There is a workaround that is using partial specialization:
template<size_t rows, size_t cols, typename T, typename Allocator>
class Matrix
{
// Notice the additionnal dummy parameter
// vvvvvvvvvvvvv
template <typename storage = Column_Major, bool = true>
class Iterator
{
};
// Specialization
template <bool dummy>
class Iterator<Row_Major, dummy>
{
};
};
You can make Synxis answer (use of defaulted dummy parameter) even more clean with C++11:
/// template <typename X>, not needed for the example
struct Outer
{
private:
template <typename A, typename D = void>
struct Inner
{
Inner() { cout << "default" << endl; }
};
template <typename D>
struct Inner<int,D>
{
Inner() { cout << "int" << endl; }
};
public:
template <typename T>
using Nested = Inner<T>;
};
The advantage of this improvement is that the signature of Nested has only one template parameter, which I think will help if you want to match it correctly in template meta-programming.
I'm surprised the template parameter for the nested class isn't a parameter of the parent class instead.
The nested class can use the template parameters of the parent and this more closely ties the nested class to the parent. Your use of the word iterator suggests this is good, the iterator surely iterating over the same type the parent contains?
I'd do it like this:
template <class T>
class Outer
{
public:
class Inner
{
void Fn( T in )
{
}
};
};
// specialisation
void Outer<double>::Inner::Fn( double in )
{
}