【问题标题】:Traits and passing traits as template parameters特征和传递特征作为模板参数
【发布时间】:2011-06-25 09:38:30
【问题描述】:

什么时候将特征作为模板参数传递而不是简单地使用一些现有的特征结构,如

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.
}

这样设计特征是否被视为traits-blob

【问题讨论】:

标签: c++ templates idioms traits


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    看到您可以为特征提供默认值,并且使用特征参数总是更灵活,我会选择这种方法,除非您有一些无法做到的具体原因。

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

    【讨论】:

    • 再次阅读这个问题,我承认答案可能与它无关,因为在第二次阅读时我真的不知道这个问题是关于什么的。它与 Foo 模板类的定义无关,仅与特征本身有关。答案很简单:当现成的特质适合你时,使用它们,如果不适合,提供你自己的。
    【解决方案3】:

    特征的设计和其他任何东西一样都是艺术。没有硬和 在这里快速回答。我相信这个问题没有得到解答,因为它是 如果对问题有更多了解,不可能给出一个好的答案 你正在解决。

    一般来说,特征类是一个有用的“定制点”。也就是说,如果你 正在设计模板:

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

    TileContainer 可能会将tile_traits&lt;Tile&gt; 用于 Tile 的某些属性。 而TileContainer 的客户可以专门化tile_traits&lt;MyTile&gt; 以便 当默认特征(如果存在)时传达属性的变化 不正确。

    到目前为止,我认为我没有说过任何你不知道的事情(从 您问题的措辞方式)。

    我认为你的问题是:

    你应该设计吗:

    一)

    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&lt;MyTile&gt;.

    用途:

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

    当您怀疑您的客户可能需要不同的特征时 Tile,或者当你想强制 TileContainer 的类型不同的时候 使用了 tile_traits 以外的一些 trait。

    【讨论】:

    • 这几乎总结了我对问题 #1 的所有疑问。正如你所说,我认为问题 #2 的答案几乎不可能有一个好的答案,并且与风格更相关,我想我可以选择 C++ Template Metaprogramming 所拥有的暂时说一下
    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多