Возможно ли убрать член класса в зависимости от параметра?
От: Van_Der_Lokken  
Дата: 03.10.10 08:42
Оценка:
Йоу. Есть следующее определение шаблонного класса:
template<
  class Attribute1,
  class Attribute2 = void,
  class Attribute3 = void,
  class Attribute4 = void
>
class Entity {
  public:
    typename Attribute1::Type _attribute1;
    typename Attribute2::Type _attribute2;
    typename Attribute3::Type _attribute3;
    typename Attribute4::Type _attribute4;
};

При таком определении класс можно специализировать только четырьмя параметрами, каждый из которых должен быть классом, в котором определено имя Type. Число параметров 4 взято для примера. При реальном использовании шаблонных параметров может быть до 16.

Теперь о том, что хочется. Хочется, чтобы те члены _attributeN, для которых соответствующий шаблонный параметр AttributeN является void, убирались из определения класса. Иными словами, хочется, чтобы при специализации вида Entity< ConcreteAttribute1 >, код компилировался, и в классе был единственный член _attribute1; чтобы при специализации вида Entity< ConcreteAttribute1, ConcreteAttribute2 > в классе были только члены _attribute1 и _attribute2 и т.д. Возможно ли это осуществить каким-либо образом?

P.S.: несмотря на то, что смысл задачи состоит в описании кортежа, заменить её на использование std::tuple по некоторым причинам невозможно.
c++ template
Re: Возможно ли убрать член класса в зависимости от параметр
От: _nn_  
Дата: 03.10.10 10:00
Оценка:
Здравствуйте, Van_Der_Lokken, Вы писали:

V_D>P.S.: несмотря на то, что смысл задачи состоит в описании кортежа, заменить её на использование std::tuple по некоторым причинам невозможно.

Раз вы знакомы с boost::tuple, то можете взять идею из реализации.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Возможно ли убрать член класса в зависимости от параметр
От: Bell Россия  
Дата: 03.10.10 10:41
Оценка:
Здравствуйте, Van_Der_Lokken, Вы писали:

Банальнейшее решение в лоб:
template<class attr>
struct attr1
{
   typename attr::Type attribute1_;
};

template<>
struct attr1<void> {};

template<class attr>
struct attr2
{
   typename attr::Type attribute2_;
};

template<>
struct attr2<void> {};

template
<
  class Attribute1,
  class Attribute2 = void
>
class Entity : public attr1<Attribute1>, public attr2<Attribute2>
{
};

struct s1
{
   typedef int Type;
};

int main()
{
   Entity<s1> e;
   e.attribute1_ = 0;//ok
   e.attribute2_ = 0;//error
   return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re[2]: Возможно ли убрать член класса в зависимости от парам
От: Van_Der_Lokken  
Дата: 03.10.10 11:31
Оценка:
Здравствуйте, Bell, Вы писали:

B>Банальнейшее решение в лоб: ...


Спасибо. Это простое и хорошее решение, но не идеальное. Я тоже думал о варианте с наследованием, но мне он не совсем понравился по той причине, что Entity перестаёт быть aggregate-классом (то есть, у Entity вообще не оказывается ни конструктора, ни aggregate-инициализации, что неприятно). Но если никто не предложит ничего лучше, то именно это решение я и использую.
Re: Возможно ли убрать член класса в зависимости от параметр
От: night beast СССР  
Дата: 04.10.10 03:59
Оценка:
Здравствуйте, Van_Der_Lokken, Вы писали:

V_D>Йоу. Есть следующее определение шаблонного класса:


V_D>При таком определении класс можно специализировать только четырьмя параметрами, каждый из которых должен быть классом, в котором определено имя Type. Число параметров 4 взято для примера. При реальном использовании шаблонных параметров может быть до 16.


V_D>Теперь о том, что хочется. Хочется, чтобы те члены _attributeN, для которых соответствующий шаблонный параметр AttributeN является void, убирались из определения класса. Иными словами, хочется, чтобы при специализации вида Entity< ConcreteAttribute1 >, код компилировался, и в классе был единственный член _attribute1; чтобы при специализации вида Entity< ConcreteAttribute1, ConcreteAttribute2 > в классе были только члены _attribute1 и _attribute2 и т.д. Возможно ли это осуществить каким-либо образом?


к варианту Bell можно добавить вариант со специализацией, если нет идеологических предубеждений против макросов.
пример здесь
Автор: night beast
Дата: 11.08.10


V_D>P.S.: несмотря на то, что смысл задачи состоит в описании кортежа, заменить её на использование std::tuple по некоторым причинам невозможно.


по каким? std::tuple легко переписывается своими силами с нужной функциональностью.
Re: Возможно ли убрать член класса в зависимости от параметр
От: Erop Россия  
Дата: 04.10.10 08:28
Оценка:
Здравствуйте, Van_Der_Lokken, Вы писали:

V_D>Теперь о том, что хочется. Хочется, чтобы те члены _attributeN, для которых соответствующий шаблонный параметр AttributeN является void, убирались из определения класса. Иными словами, хочется, чтобы при специализации вида Entity< ConcreteAttribute1 >, код компилировался, и в классе был единственный член _attribute1; чтобы при специализации вида Entity< ConcreteAttribute1, ConcreteAttribute2 > в классе были только члены _attribute1 и _attribute2 и т.д. Возможно ли это осуществить каким-либо образом?


Нужно ли уметь пропускать атрибут в центре списка? Если нет, то можно сделать 16 частичных специализаций...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Возможно ли убрать член класса в зависимости от парам
От: Владислав Курмаз Украина http://tis-method.org/
Дата: 04.10.10 10:38
Оценка:
Здравствуйте, Van_Der_Lokken, Вы писали:

V_D>Здравствуйте, Bell, Вы писали:


B>>Банальнейшее решение в лоб: ...


V_D>Спасибо. Это простое и хорошее решение, но не идеальное. Я тоже думал о варианте с наследованием, но мне он не совсем понравился по той причине, что Entity перестаёт быть aggregate-классом (то есть, у Entity вообще не оказывается ни конструктора, ни aggregate-инициализации, что неприятно). Но если никто не предложит ничего лучше, то именно это решение я и использую.


Здесь без наследования не обойтись.
Для себя решал подобную задачу и пришёл к следующую решению (используется как базовое для весокоуровневых компонентов)
template < class, size_t >
struct slot;

template < size_t I >
struct slot< Loki::NullType, I >
{
    ///
    typedef Loki::NullType
        value_type;
    ///
    value_type
        value;
};

template < typename T, typename U, size_t I >
struct slot< Loki::Typelist< T, U >, I > : public slot< U, I + 1 >
{
    ///
    typedef T
        value_type;
    ///
    value_type
        value;
};

Аналогичное Loki::GenLinearHierarchy.
Можно посмотреть здесь здесь файл z3d/slot.hpp
Re[2]: Возможно ли убрать член класса в зависимости от парам
От: Van_Der_Lokken  
Дата: 04.10.10 10:39
Оценка:
Здравствуйте, Erop, Вы писали:

E>Нужно ли уметь пропускать атрибут в центре списка? Если нет, то можно сделать 16 частичных специализаций...


На самом деле, не нужно. И этот вариант с кучей специализаций под разное число параметров приходит в голову самым первым. Он плох тем, что появляется чёртова прорва практически одинакового кода. И неизбежный в этом случае copy-paste, как известно, является первым признаком того, что код организован неудачно.
Re[2]: Возможно ли убрать член класса в зависимости от парам
От: Van_Der_Lokken  
Дата: 04.10.10 11:17
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, Van_Der_Lokken, Вы писали:


V_D>>P.S.: несмотря на то, что смысл задачи состоит в описании кортежа, заменить её на использование std::tuple по некоторым причинам невозможно.


NB>по каким? std::tuple легко переписывается своими силами с нужной функциональностью.


Сам по себе std::tuple не годится, так как никто не гарантирует, что элементы кортежа будут расположены в памяти в том же порядке, в каком были указаны в списке параметров шаблона, и что между ними не окажется padding-байтов. А та структура данных, что мне нужна, должна удовлетворять этим требованиям. Скажем, в моём компиляторе sizeof( std::tuple<uint32_t> ) == 8. Если я всё правильно понимаю, в реализации кортежа 4 байта всегда обязательно уходит на некий "хвостовой" элемент. В моём случае неприемлемо.
Re[3]: Возможно ли убрать член класса в зависимости от парам
От: night beast СССР  
Дата: 04.10.10 11:31
Оценка:
Здравствуйте, Van_Der_Lokken, Вы писали:

V_D>>>P.S.: несмотря на то, что смысл задачи состоит в описании кортежа, заменить её на использование std::tuple по некоторым причинам невозможно.


NB>>по каким? std::tuple легко переписывается своими силами с нужной функциональностью.


V_D>Сам по себе std::tuple не годится, так как никто не гарантирует, что элементы кортежа будут расположены в памяти в том же порядке, в каком были указаны в списке параметров шаблона, и что между ними не окажется padding-байтов. А та структура данных, что мне нужна, должна удовлетворять этим требованиям. Скажем, в моём компиляторе sizeof( std::tuple<uint32_t> ) == 8. Если я всё правильно понимаю, в реализации кортежа 4 байта всегда обязательно уходит на некий "хвостовой" элемент. В моём случае неприемлемо.


никаких хвостовых элементов в тупле нет.
список типов известен на момент компиляции, поэтому в нем нет необходимости.
возможно, в конце наследования есть пустая структура, но нормальные компиляторы умеют делать EmptyBaseOptimisation.
если твой не может, то "std::tuple легко переписывается своими силами". в своем велосипеде крайним делается тупл из одного элемента, и все дела.
Re[3]: Возможно ли убрать член класса в зависимости от парам
От: Erop Россия  
Дата: 04.10.10 14:38
Оценка:
Здравствуйте, Van_Der_Lokken, Вы писали:

V_D>На самом деле, не нужно. И этот вариант с кучей специализаций под разное число параметров приходит в голову самым первым. Он плох тем, что появляется чёртова прорва практически одинакового кода. И неизбежный в этом случае copy-paste, как известно, является первым признаком того, что код организован неудачно.


генерить одинаковый код можно поручить макросам...

Но в целом мне кажется, что сама по себе задача какая-то подозрительная. Зачем это всё в целом вообще надо?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.