Reputation: 11
I am trying to use a member type of a template class, which does not depend on any template parameters of the template class. I would like to keep the type as the member type due to its logic, but I do not want to specify the unnecessary template parameters of the class whenever I want to use the member type outside the class.
Consider the following:
class Dummy { };
// Template class
template<typename T>
class A {
public:
template<typename T2>
class MemberType : public T2 {
public:
T2 t2;
};
};
int main()
{
typename A<Dummy>::template MemberType<Dummy> m1; // okay
typename A::template MemberType<Dummy> m2; // not okay!
return 0;
}
I got the following compiler error when I try to compile using g++:
error: ‘template<class T> class A’ used without template parameters
typename A::template MemberType<Dummy> m2; // not okay!
Is there any workaround for this?
Upvotes: 1
Views: 1201
Reputation: 66230
Is there any workaround for this?
MemberType
is a type dependent from a template parameter so, necessarily, you have to pass through the containing template a template parameter to define it
typename A<SomeType>::template MemberType<AnotherType> m2;
Taking in count that your not interested in external SomeType
parameter, the best workaround I can imagine is the use of a using
as follows (or something similar)
template <typename T>
using MemberType_t = typename A<T>::template MemberType<T>;
to reduce typewriting.
The following is a full compiling simplified example
#include <type_traits>
class Dummy { };
template <typename>
struct A
{
template <typename T2>
struct MemberType : public T2
{ T2 t2; };
};
template <typename T>
using MemberType_t = typename A<T>::template MemberType<T>;
int main ()
{
typename A<Dummy>::template MemberType<Dummy> m1;
MemberType_t<Dummy> m2; // compile
static_assert( std::is_same<decltype(m1), decltype(m2)>::value, "!" );
}
Upvotes: 0
Reputation: 10982
Everything in a template is dependent on the parameter(s) - meaning a template-specialization might not even have class MemberType
.
But you can make a default parameter - you still need to write <>
though (but you can omit template
usually - even typename
, but I left that):
class Dummy { };
// Template class
template <class T = void>
class A {
public:
template<typename T2>
class MemberType : public T2 {
public:
T2 t2;
};
};
int main()
{
typename A<Dummy>::MemberType<Dummy> m1; // okay
typename A<>::MemberType<Dummy> m2; // also ok
return 0;
}
As others have pointed out, this somewhat looks like an anti-pattern though - since the inner type is not dependent on the parameter of the outer template class.
Upvotes: 1
Reputation: 122726
What you want to do is not possible. A template is just a template. There is very little you can do with it before actually instantiating it for a concrete type. There could be a specialization for A
that has no nested MemberType
at all.
I would like to keep the type as the member type due to its logic, [...]
...but it seems the logic is something else: The MemberType
does not depend on A
, hence it should not be part of a template that depends on A
.
Sloppy speaking template<typename T>
can be read as "everything that follows depends on T
". Even if you think it does not, there could always be a specialization that changes anything inside A
. If you want MemberType
to not depend on T
then declare it outside A
.
Upvotes: 1
Reputation: 5321
I am trying to use a member type of a template class, which does not depend on any template parameters of the template class.
As a nested type within class A<T>
, MemberType
does depend on the template parameter T
.
i.e. A<T>::MemberType<T2>
and A<U>::MemberType<T2>
are distinct classes.
Upvotes: 1