S
S
Samu3l2012-08-27 11:26:05
C++ / C#
Samu3l, 2012-08-27 11:26:05

Is it appropriate to use a macro to define a specialization of a template class?

Hello!

There was a need to pass a string with a regular expression as a template parameter. To do this, it was decided to pass as a template parameter of the target class a class containing a method that returns the required string.

enum RequestCode
{
  REQUEST_CODE_1,
  REQUEST_CODE_2
};


template< int REQUEST_CODE >
class RequestRegex;


template<>
class RequestRegex< REQUEST_CODE_1 > : private ::simple::StaticClass
{
public :
  static std::string get()
  {
    static const std::string regexString( "\\w{3,100}" );
    return regexString;
  }
};


template<>
class RequestRegex< REQUEST_CODE_2 > : private ::simple::StaticClass
{
public :
  static std::string get()
  {
    static const std::string regexString( "\\d{1,15}" );
    return regexString;
  }
};


// Определение целевого типа, использующего строки регулярных выражений
typedef SomeRequest< REQUEST_CODE_1, RequestRegex< REQUEST_CODE_1 > > Request1;
typedef SomeRequest< REQUEST_CODE_2, RequestRegex< REQUEST_CODE_2 > > Request2;


Dozens of such specializations are required. It is possible to significantly shorten the code using a macro like this:

template< int REQUEST_CODE >
class RequestRegex;


#define MACRO_TEMPLATE_CLASS_REQUEST_REGEX( REQUEST_CODE, REGEX_STRING ) \
  template<>\
  class RequestRegex< REQUEST_CODE > : private ::simple::StaticClass\
  {\
  public :\
    static std::string get()\
    {\
      static const std::string regexString( REGEX_STRING );\
      return regexString;\
    }\
  }


MACRO_TEMPLATE_CLASS_REQUEST_REGEX( REQUEST_CODE_1, "\\w{3,100}" );
MACRO_TEMPLATE_CLASS_REQUEST_REGEX( REQUEST_CODE_2, "\\d{1,15}" );

// Определение целевого типа, использующего строки регулярных выражений
typedef SomeRequest< REQUEST_CODE_1, RequestRegex< REQUEST_CODE_1 > > Request1;
typedef SomeRequest< REQUEST_CODE_2, RequestRegex< REQUEST_CODE_2 > > Request2;


Passing a string with a regular expression to the constructor of the target type is not desirable, since the code using it does not have to control which regular expression is used and does not even need to know that it is there.

Do you think it is rational to use macros in this situation? If not, is there another way?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
G
Gribozavr, 2012-08-28
@Samu3l

template<const char *p> struct Z {};
extern const char X[] = "aaa";
Z<X> A;

Why not make it easier?

M
Mephi1984, 2012-08-27
@Mephi1984

If you create a separate data type for each regular expression, then what prevents you from doing polymorphism through all? Define virtual std::string get() = 0 in the base class, and describe a different implementation in the descendants?

F
Fahrenheit, 2012-08-27
@Fahrenheit

As for me, the solution with factories is better. If the RequestXX classes are not trivial, then you can easily end up with serious code duplication in the final executable.
Of course, the effect depends on the task and the number of specializations, but in any case, this is not good.
And inside the factories, you can already produce any designs that you want - their implementation is hidden.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question