Ronin Goda
Ronin Goda

Reputation: 234

c++ template with typedef multiple argument?

I have a template class with 5 template arguments which looks something similar to this.

SomeClass.h

template < typename A, typename B, typename C, typename D >
class SomeClass
{
private:
A a_obj;
B b_obj;
C c_obj;
D d_obj;
public:
void someoperationA();
void someoperationB();
void someoperationC();
};

SomeClass.cpp

template < typename A, typename B, typename C, typename D >
SomeClass<A, B, C, D>::someoperationA()
{
 A::someStaticMethods();
}

template < typename A, typename B, typename C, typename D >
SomeClass<A, B, C, D>::someoperationB()
{}

template < typename A, typename B, typename C, typename D >
SomeClass<A, B, C, D>::someoperationC()
{}

Consider the case where my template parameters should be given some good big names like

SomeClass.cpp

template < 
typename ABIGCLASSNAME, 
typename BBIGCLASSNAME, 
typename CBIGCLASSNAME, 
typename DBIGCLASSNAME 
>
SomeClass<ABIGCLASSNAME, 
BBIGCLASSNAME, 
CBIGCLASSNAME, 
DBIGCLASSNAME>::someoperationA()
{
ABIGCLASSNAME::someStaticMethods();
}

It definitely starts looking ugly :(

So is it possible to typedef template arguments in any way, so that its readable... Something like

typedef template < typename ABIGCLASSNAME, typename BBIGCLASSNAME, typename CBIGCLASSNAME, typename DBIGCLASSNAME > TEMP_WITH_PARAMS

and something simliar for the class other than using #define

Upvotes: 0

Views: 1777

Answers (3)

lapk
lapk

Reputation: 3918

Descriptive template parameters' names are nice. But once you specified them initially, you don't have to drag them around. Two things can help you:

  1. using to have a short alias inside the class.
  2. The fact that you don't have to use same name for template parameter for definitions outside the class.

    #include <iostream>
    template <typename SomeLongAndUglyName>
    class ImPretty {
      public: 
        using SimplyUgly = SomeLongAndUglyName;
    
      void foo();
    };
    
    template <typename Ugly>
    void ImPretty<Ugly>::foo() {
      std::cout << "pretty" << std::endl;
    }
    

Upvotes: 0

Vittorio Romeo
Vittorio Romeo

Reputation: 93264

Consider creating a wrapper struct that contains all of your required parameters, and templatize SomeClass on that:

template < typename A, typename B, typename C, typename D >
struct Settings
{
    using AType = A;
    using BType = B;
    using CType = C;
    using DType = D;
};

template < typename TSettings >
class SomeClass { /* ... */ } 

template < typename TSettings >
SomeClass<TSettings>::someoperationB() { /* ... */ }

Advantages:

  • Much less boilerplate.

  • If you decide to add a new template parameter or change an existing one, you only have to change Settings.

Preserving your original interface is also trivial with a type trait:

template < typename A, typename B, typename C, typename D >
using SomeClass = SomeClassImpl<Settings<A, B, C, D>>;

Consider using a variadic type trait to avoid repeating A, B, C, D:

template < typename... Ts >
using SomeClass = SomeClassImpl<Settings<Ts...>>;

Upvotes: 2

bolov
bolov

Reputation: 75688

No, there isn't.

Be careful, you can't have templated definitions in source (.cpp) files. See Why can templates only be implemented in the header file?

There was a proposal to define a class namespace where all definitions were considered members of that class, which would have solved your problem, but it didn't get much traction.

So either write all templates paramters (but in headers), or define them inside the class. I personally prefer defining the methods inside class, since I have to define then in headers anyway, I don't see a much advantage to defining them outside of class vs the hassle to write code twice.

Another trick you can do is to have really short template parameter names and have full name aliases in class. E.g.:

template <class F> struct S {
   using Function = F;
};

Upvotes: 2

Related Questions