特征和将特征作为模板参数传递

7
何时将特征作为模板参数传递而不是仅使用某些现有的特征结构,例如 typedef basic_ofstream< char, char_traits<char> >typedef basic_ofstream< char > 相比较实用?
我有一些瓷砖类,我想要它们具有一些共同点(特征),因此我设计了tile_traits来包含有关瓷砖的所有基本信息,例如int_typeflag_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.
}

设计特征本身是否被视为“特征blob(traits-blob)”?

术语traits-blob对我来说是未知的。它在另一个问题https://dev59.com/g0rSa4cB1Zd3GeqPYrnJ中提到。 - Suma
3个回答

13

特性的设计与艺术一样,没有固定答案。我认为这个问题一直没有得到回答是因为我们需要更多关于你正在解决的问题的信息。

通常来说,特性类是一个有用的"自定义点"。也就是说,如果你在设计一个模板:

template <class Tile>
class TileContainer
{
    ...
};
TileContainer 可能会利用 tile_traits<Tile> 来处理 Tile 的某些属性。而 TileContainer 的客户端可以专门为 MyTile 定制 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以外的某些特征时不同。


这基本上概括了我对问题#1的所有疑问。我认为问题#2的答案,就像你所说的那样,几乎不可能有一个好的答案,并且更与风格相关,我想现在可以只按照C ++模板元编程所说的去做。 - Khaled Nassar

6

如果您可以看到人们会为相同的数据类型传递不同的traits,那么您需要将traits类作为模板参数。如果您的瓷砖对于每个T都具有相同的tile_traits,则可以直接使用它。

如果您可以看到有人有时会使用my_special_traits,则需要将其作为单独的模板参数。


1

看到你可以为traits提供默认值,而且使用traits参数始终更加灵活,除非你有一些特殊的原因不能这样做,否则我会选择这种方法。

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

再次阅读问题,我承认答案可能与之无关,因为第二次阅读时,我真的不知道这个问题是关于什么的。它似乎与Foo模板类的定义无关,只与特性本身有关。在那里,答案很简单:当现成的特性适合您时,请使用它们;否则,请提供您自己的特性。 - Suma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接