使用通用矢量大小类型的最佳方法是啥?
Posted
技术标签:
【中文标题】使用通用矢量大小类型的最佳方法是啥?【英文标题】:What is the best way to use a common vector size type?使用通用矢量大小类型的最佳方法是什么? 【发布时间】:2012-01-11 18:12:02 【问题描述】:创建模板化矢量类时,允许使用其大小类型的最佳方式是什么?从我收集到的信息来看,似乎是为真正的向量类创建一个接口,然后使用它。比如
for(VectorBase::size_type i = 0; i < test1.size(); ++i)
这比
有优势for(Vector<int>::size_type i = 0; i < test1.size(); ++i)
用于使代码更简洁,并且不必知道 Vector 的模板类型(以防它发生变化)。
我的实现示例(如果有更好的方法,这是我创建它的方法)。
class VectorBase
public:
typedef unsigned int size_type;
protected:
size_type mCount;
public:
VectorBase() mCount = 2;
virtual ~VectorBase() = 0
size_type size() const return mCount;
;
template<typename Type>
class Vector : public VectorBase
public:
Vector() : VectorBase()
~Vector()
;
int main(void)
Vector<int> test1;
for(VectorBase::size_type i = 0; i < test1.size(); ++i)
cout << i << endl;
system("PAUSE");
return(0);
(注意:请不要把它变成“Just use xxx vector class”)。
【问题讨论】:
如果发现您希望size_type
依赖于您的模板参数会怎样?
我更喜欢通过迭代器访问而不是索引访问——它更通用、更灵活,除非实际的索引值本身具有某种意义。
@Grizzly,我不担心我的 size_type 来自模板参数。它永远是一样的。
@Kerrek SB,我同意大多数情况下应该使用迭代器。这是为了演示 size_type 的使用方式,并且想知道应该以哪种方式访问它。
【参考方案1】:
不必知道 Vector 的模板类型(以防它发生变化)。
如果您担心容器类型发生变化,可以:
-
为其创建一个 typedef,因此
test1
使用循环中使用的相同类型名称声明,但该名称表示的类型将来可能会更改。
编写适当的泛型函数,因此容器的类型是模板参数T
或其他类型,并且您使用typename T::size_type
作为i
的类型。然后,如果类型发生变化,您的代码就会应对。
(1)的例子:
typedef vector<int> test_type;
test_type test1;
// populate the vector
for (test_type::size_type i = 0; i < test1.size(); ++i) std::cout << i << '\n';
(2)的例子:
template <typename Container>
void print_indexes(const Container &test1)
for (typename Container::size_type i = 0; i < test.size(); ++i)
std::cout << i << '\n';
替代解决方法:
1) 只需使用std::size_t
。有点作弊,因为原则上我认为vector<bool>
可以有多个SIZE_MAX
元素,但没有“正确”的向量可以比这更大。
2)(仅限 C++11)使用 auto
作为 i
的类型
for (auto i = test.size(); i != 0; --i) std::cout << (test.size() - i) << '\n';
或
for (decltype(test.size()) i = 0; i < test1.size(); ++i) ...
我个人会遵循标准库中使用的样式,而不是为容器类模板使用公共基类。
【讨论】:
另一个人提到了你的第二点,我很感兴趣。如果我要删除 VectorBase,那么模板是“templatetemplate<typename Type, typename SizeType = unsigned int> class myvector public: typedef Type value_type; typedef SizeType size_type; ;
。
我怎样才能轻松访问 size_type 值呢?看起来我需要做一些类似“Vector我认为没有最好的方法。 :-)
通过将某些部分移至公共基类,您可以简化接口,但您也可以选择模板的派生类或特化。
例如,如果您希望 vector<char>
包含大量字符,则可能需要 long long
大小类型。 vector<my_huge_type>
的潜在专业化可能只需要 int
?
我们是否应该预先决定 unsigned int 总是足够好?也许,也许不是。经常设计界面以在复杂性和灵活性之间找到良好的平衡。
【讨论】:
你提出了一个很好的观点。因此,如果我要删除 VectorBase,然后让模板为“templateVector<char, int>
和Vector<char, long>
,这似乎是太多 的灵活性。 :-)
@Bo:带符号的大小类型绝对是太灵活了!
我非常怀疑是否存在,但有没有办法只有无符号大小?
我使用带符号的类型只是为了表明它是一个让 size_type 与 ptrdiff_t 相同的选项。标准容器没有这个部分是因为这会将 vector既然已经有了完美的Vector,为什么还要重写?
如果您确实必须从 VectorBase 继承,但最好给 VectorBase 一个受保护的析构函数而不是一个公共虚拟析构函数,因为现在您已经给 Vector 一个 v-table。
顺便说一句,纯虚拟析构函数的语法不是标准的。
在每个向量模板中保留 size_type 的 typedef 没有编译器开销(即膨胀),因此移动它不会有很大的优势。
【讨论】:
@CashCow,我的最后一行是“(注意:请不要把它变成“只需使用 xxx 向量类。”)。我的纯虚拟析构函数怎么不标准? 虽然有些编译器允许,但标准中不允许在 = 0 后面加上 。 那应该怎样, = 0?以上是关于使用通用矢量大小类型的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章