Я работаю над добавлением нового контента в старую программу, которая везде использует метапрограммирование. Я все еще на C++ 03 и повышу. Так вот проблема: я сделал шаблон функции, что я не хочу, чтобы специализироваться из-за различий только в четырех вызовов функции, чтобы получить конкретные значения:Метапрограммирование, пытаясь избежать многих специализаций
template < typename Message >
void function(const Message & message)
{
....
int value = getHelper...getValue();
....
}
Есть много различных типов сообщений:
MessageA: public BaseForA<MessageA>
MessageB: public BaseForB<MessageB>
template < typename Appendage > MessageAWithAppendage <Appendage>: public BaseForA< MessageA <Appendage> >
template < typename Appendage > MessageB: public BaseForB<MessageB>: public BaseForB< MessageB <Appendage> >
И два придатков тип:
SmallAppendage
BigAppendage
Существует переменное условие в заголовке каждого сообщения, в зависимости от этого getValue()
должен получить поле из сообщения или возвращать ноль. Это поле может быть в самом сообщении, если тип без придатка, или в придатке ИЛИ в то же время в самом сообщении, если сообщение с придатком.
мне нужно что-то вроде класса Base для сообщений без придатков и Extended для сообщений с придатком что-то вроде:
template < typename Message >
class Helper
{
public:
virtual int getValue(const Message & msg)
{
if(..)
{
return msg.value;
}
...
}
};
template< template <class> class Message, typename Appendage >
class ExtendedHelper : public Helper < Message <Appendage> >
{
public:
virtual int getValue(const Message<Appendage> & msg)
{
int value = Helper::getValue(msg);
if(value)
{
return value;
}
return msg.appendage.getValue();
}
};
После того, что я думал, что-то, как это будет работать, но это не так:
template < class Type >
struct AppendageTraits
{
enum { appendageIncluded = false };
};
template < class Appendage >
struct AppendageTraits < MessageAWithAppendage <Appendage> >
{
enum { appendageIncluded = true };
};
template < class Appendage >
struct AppendageTraits < MessageBWithAppendage <Appendage> >
{
enum { appendageIncluded = true };
};
template< typename Message , bool >
struct GetHelper
{
Helper<Message> * operator()()
{
static Helper<Message> helper;
return &helper;
}
};
EDIT: Мои черты теперь компилируются. Можно ли сделать эту работу:
template < typename Appendage >
struct GetHelper<MessageAWithAppendage <Appendage>, true>
{
Helper< MessageAWithAppendage <Appendage> > * operator()()
{
static Helper< MessageAWithAppendage <Appendage>, Appendage > helper;
return &helper;
}
};
template < typename Appendage >
struct GetHelper<MessageBWithAppendage <Appendage>, true>
{
Helper< MessageBWithAppendage <Appendage> > * operator()()
{
static ExtendedHelper< MessageBWithAppendage <Appendage>, Appendage > helper;
return &helper;
}
};
EDIT: теперь имеют тип/несоответствие значений в параметре 1 для
static ExtendedHelper< MessageAWithAppendage <Appendage>, Appendage > helper;
ожидается шаблон класса получил .. класс шаблон !, но это не как-то определенно.
EDIT: Я решил эту ошибку, из-за этого:
Как и обычные (не шаблон) классов, шаблоны классов имеют впрыскивается-имя-класса (пункт 9). Имя введенного класса может использоваться с или без шаблона-аргумента-списка. Когда он используется без списка шаблонов-аргументов, он эквивалентен имени введенного класса, за которым следуют шаблонные параметры шаблона класса, заключенного в <>. Когда он используется с шаблоном-аргументом-списком, он ссылается на указанную специализацию шаблона класса, которая может быть текущей специализацией или другой специализацией.
Правильный код:
template < typename Appendage >
struct GetHelper<MessageAWithAppendage <Appendage>, true>
{
Helper< MessageAWithAppendage <Appendage> > * operator()()
{
static Helper< MessageAWithAppendage, Appendage > helper;
return &helper;
}
};
template < typename Appendage >
struct GetHelper<MessageBWithAppendage <Appendage>, true>
{
Helper< MessageBWithAppendage <Appendage> > * operator()()
{
static ExtendedHelper< MessageBWithAppendage, Appendage > helper;
return &helper;
}
};
Мне понадобится 4 таких хэпера с 6 специализациями, это на случай, если я не найду, как сделать его более компактным. – Ambrase
Продолжайте находить общие вещи, чтобы специализироваться на. Некоторые из функций-членов могут быть самими шаблонами. Они создают новые геттеры. –
Это то, чего я пытаюсь достичь. Взгляните на обновленный вопрос, если я найду, как заставить помощников работать моими качествами сейчас, все будет компактным. – Ambrase