Черты и передаваемые черты как параметры шаблона - PullRequest
7 голосов
/ 11 февраля 2011

Когда целесообразно передавать черты в качестве параметров шаблона, а не просто использовать существующую структуру черт, такую ​​как

typedef basic_ofstream< char, char_traits<char> >

против.

typedef basic_ofstream< char >

У меня есть несколько классов плиток, которые я хотел бы иметь некоторые общие черты (черты), поэтому я разработал tile_traits, чтобы содержать всю основную информацию о плитке, такую ​​как int_type и flag_type, например:

//unspecialized
template<typename T> struct tile_traits;
//... other stuff here, declaration of a tile class
template<>
struct tile_traits<tile_class>
{
   typedef tile_class::int_type  int_type;
   typedef tile_class::flag_type flag_type;
   //other possible tile info here.
}

Является ли проектирование черт как таковых признаком-блобом ?

Ответы [ 3 ]

13 голосов
/ 13 февраля 2011

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

В целом классы черт являются полезной «точкой настройки».То есть, если вы разрабатываете шаблон:

template <class Tile>
class TileContainer
{
    ...
};

TileContainer может использовать tile_traits<Tile> для некоторых свойств Tile.И клиент TileContainer может специализироваться tile_traits<MyTile> для передачи изменений свойств, когда черта по умолчанию (если она существует) не верна.

Пока я не думаю, что сказалвсе, что вы еще не знаете (судя по тому, как сформулирован ваш вопрос).

Я думаю, что ваш вопрос:

Если вы придумаете:

A)

template <class Tile, class Traits = tile_traits<Tile>>
class TileContainer
{
    // uses Traits
};

или:

B)

template <class Tile>
class TileContainer
{
    // uses tile_traits<Tile>
};

В C ++ 03 и последующих стандартах C ++ 0x есть примеры обоих проектов.

Примеры дизайна A:

template<class charT, class traits = char_traits<charT>,
                      class Allocator = allocator<charT>>
    class basic_string;  // both traits and Allocator are traits

template <class Codecvt, class Elem = wchar_t,
                         class Tr = char_traits<Elem>>
    class wbuffer_convert;

template <class T, class Allocator = allocator<T>>
    class vector; // Allocator is a A-trait that uses another
                  // B-trait internally:  allocator_traits<Allocator>

template <class charT, class traits = regex_traits<charT>>
    class basic_regex;

Примеры дизайна B:

template<class Iterator> struct iterator_traits;
template <class Alloc> struct allocator_traits;
template <class Ptr> struct pointer_traits;
template <class Rep> struct treat_as_floating_point;
template <class Rep> struct duration_values;

Мой единственный совет - нет правильного или неправильного дизайна.Используйте:

template <class Tile>
class TileContainer
{
    // uses tile_traits<Tile>
};

, если вы уверены, что потребности вашего клиента всегда можно удовлетворить, специализацией tile_traits<MyTile>.

. Используйте:

template <class Tile, class Traits = tile_traits<Tile>>
class TileContainer
{
    // uses Traits
};

, когда вы подозреваете, чтовашему клиенту могут потребоваться разные характеристики для одного и того же элемента Tile или когда вы хотите, чтобы тип TileContainer был другим, если используется какая-либо характеристика, отличная от tile_traits.

6 голосов
/ 13 февраля 2011

Вам необходимо иметь класс черт в качестве параметра шаблона, если вы видите, что люди передают разные черты для одного и того же типа данных. Если ваши плитки всегда будут иметь одинаковые tile_traits для каждого T, вы можете использовать это напрямую.

Если вы видите, что кто-то иногда использует my_special_traits, вы должны указать это как отдельный параметр шаблона.

1 голос
/ 13 февраля 2011

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

template<class Bar,class Traits=FooTraits<Bar> >
class Foo
{};
...