Samu3l
@Samu3l

Уместно ли использование макроса для определения специализации шаблонного класса?

Здравствуйте!

Возникла потребность в передаче строки с регулярным выражением в качестве шаблонного параметра. Для этого решено было передавать в качестве шаблонного параметра целевого класса класс, содержащий метод, возвращающий требуемую строку.

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;


Подобных специализаций требуется несколько десятков. Возможно значительно сократить код с использованием макроса так:

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;


Передавать строку с регулярным выражением в конструктор целевого типа не желательно, так как использующий его код не должен управлять тем, какое регулярное выражение используется и вобще не должен занать о том, что оно там есть.

Как вы считаете, рационально ли в этой ситуации использовать макросы? Если нет, то есть ли другой способ?
  • Вопрос задан
  • 2574 просмотра
Решения вопроса 1
@gribozavr
template<const char *p> struct Z {};
extern const char X[] = "aaa";
Z<X> A;

Почему не сделать проще?
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Mephi1984
@Mephi1984
Если на каждое регулярное выражение у вас создается отдельный тип данных, то что мешает сделать через все полиморфизм? Определить в базовом классе virtual std::string get() = 0, а в потомках описать разную реализацию?
Ответ написан
@Fahrenheit
Как по мне, лучше все же решение с фабриками. Если классы RequestXX не тривиальные, то можно запросто получить серьезное дублирование кода в финальном исполняемом файле.
Конечно, эффект зависит от задачи и количества специализаций, но в любом случае это не есть хорошо.

А внутри фабрик можно уже плодить любые конструкции, которые хочется — их реализация-то скрыта.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы