C++ 向标准模板的专门化添加新方法(std::vector、std::list…)

C++ 向标准模板的专门化添加新方法(std::vector、std::list…),c++,templates,template-specialization,C++,Templates,Template Specialization,我想为std::list创建专门化,这将为这个包含图片的列表添加额外的方法,但我不知道是否有可能以我尝试过的这种方式实现 我试过: template <typename _Alloc = std::allocator<Picture>> class list : protected _List_base<Picture, _Alloc> { public: void draw() { // some code } }; int m

我想为std::list创建专门化,这将为这个包含图片的列表添加额外的方法,但我不知道是否有可能以我尝试过的这种方式实现

我试过:

template <typename _Alloc = std::allocator<Picture>> 
   class list : protected _List_base<Picture, _Alloc>
{
public:
  void draw()
  {
    // some code
  }
};

int main()
{
  std::list<Picture> myList;
  //adding elements to mylist
  mylist.draw();
  return 0;
}
编译后,我有一个错误:

错误:“类std::_cxx11::list”没有名为“draw”的成员


标准明确允许STL类型的专门化。但是,您需要专门处理名称空间std


也继承了C++ ListBASE继承的C++标准所禁止的内容。如上所列,在程序中使用保留标识符会导致程序格式错误,并且所有以下划线开头,后跟大写字母的标识符都将保留。

标准明确允许STL类型的专门化。但是,您需要专门处理名称空间std

也继承了C++ ListBASE继承的C++标准所禁止的内容。如上所列,在程序中使用保留标识符会导致程序格式错误,并且所有以下划线开头,后跟大写字母的标识符都是保留的。

STL类型 您可以专门化STL类型,但如另一个答案中所述,它们需要在命名空间std中专门化。这意味着您应该这样做:

namespace std {
    template <typename _Alloc = std::allocator<Picture>> 
    class list<Picture, _Alloc> { 
        /* stuff */ 
    };
}
从std::list继承的注意事项 从std::list继承有一些注意事项。因为std::list不需要动态多态性,这意味着它没有虚拟析构函数或任何其他虚拟方法。您基本上只是围绕std::list创建一个包装器类

此外,如果将任何字段添加到DrawableList,则在将其复制到std::list时,这些字段可能会被截断。这称为对象切片

DrawableList<Picture> a = /* stuff */;

std::list<Picture> b = a; // This will compile without any issues

DrawableList<Picture> c = b; // Oops; any extra fields you had in a got cut off
专门化STL类型 您可以专门化STL类型,但如另一个答案中所述,它们需要在命名空间std中专门化。这意味着您应该这样做:

namespace std {
    template <typename _Alloc = std::allocator<Picture>> 
    class list<Picture, _Alloc> { 
        /* stuff */ 
    };
}
从std::list继承的注意事项 从std::list继承有一些注意事项。因为std::list不需要动态多态性,这意味着它没有虚拟析构函数或任何其他虚拟方法。您基本上只是围绕std::list创建一个包装器类

此外,如果将任何字段添加到DrawableList,则在将其复制到std::list时,这些字段可能会被截断。这称为对象切片

DrawableList<Picture> a = /* stuff */;

std::list<Picture> b = a; // This will compile without any issues

DrawableList<Picture> c = b; // Oops; any extra fields you had in a got cut off

请不要。添加非成员函数void drawstd::list const&和void drawstd::vector const&@Frank此处没有“不允许”的内容。_list_base是您正在使用的任何标准库的实现细节。它故意有个难听的名字。你不应该碰它。如果您使用不同的标准库实现切换到不同的编译器,则可能不存在。请不要这样做。添加非成员函数void drawstd::list const&和void drawstd::vector const&@Frank此处没有“不允许”的内容。_list_base是您正在使用的任何标准库的实现细节。它故意有个难听的名字。你不应该碰它。如果您切换到具有不同标准库实现的不同编译器,则可能不存在此问题。我还提到了对象切片。您可以使用私有继承解决切片问题。那么你也不必担心虚拟析构函数的缺乏。我还提到了对象切片。你可以使用私有继承来解决切片问题。那么,你不必担心虚拟析构函数的缺乏。提到令牌-ListBaseBASE,程序就不正确,在每个版本的C++中都不需要诊断。List_base是一个令牌,它只能由编译器使用,包括标准下的std库实现者。因此,这不仅不能保证有效,而且违反了格式良好的程序的明确规则。甚至不是很好的方式。@Yakk AdamNevraumont我不知道仅仅使用标识符是被禁止的。我会编辑。规则是“不”和“不前导”,后跟大写字母。std在内部使用这些标识符是因为其他程序员不允许触摸它们,比如说,将它们定义为其他东西;复制std代码的人会生成格式错误的程序。@Yakk AdamNevraumont我确实了解有关下划线的规则,但我一直认为它们适用于创建此类标识符。我不知道使用已经存在的实现和其他可见的那些也不明确。提到令牌-ListBaseBASE,在每个C++版本中,程序都不正确,不需要诊断。List_base是一个令牌,它只能由编译器使用,包括标准下的std库实现者。因此,这不仅不能保证有效,而且违反了格式良好的程序的明确规则。甚至都不是很好。@Yakk AdamNevraumont我不是aw
仅使用标识符是被禁止的。我会编辑。规则是“不”和“不前导”,后跟大写字母。std在内部使用这些标识符是因为其他程序员不允许触摸它们,比如说,将它们定义为其他东西;复制std代码的人会生成格式错误的程序。@Yakk AdamNevraumont我确实了解有关下划线的规则,但我一直认为它们适用于创建此类标识符。我不知道使用已经存在于实现中的和其他可见的也没有定义。
void draw(std::list<Picture>& pictures, int x, int y) {
    for(auto& picture : pictures) {
        picture.draw(x, y); 
    }
}