nfy
nfy

Reputation: 11

How to use member type of a template class without specifying unnecessary template parameters?

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

Answers (4)

max66
max66

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

darune
darune

Reputation: 10982

Everything in a is dependent on the parameter(s) - meaning a 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

463035818_is_not_an_ai
463035818_is_not_an_ai

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

Jeremy
Jeremy

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

Related Questions