简体   繁体   English

没有 bool 数组的类模板特化?

[英]No class template specialization for array of bool?

According to https://en.cppreference.com/ , std::vector<bool> has a class template specialization, while std::array<bool, N> does not.根据https://en.cppreference.com/std::vector<bool>具有类模板特化,而std::array<bool, N>没有。 Which are the reasons why it is not provided?不提供的原因有哪些?

When std::vector was introduced, a specialization for bool was considered a good idea.当引入std::vector时, bool被认为是一个好主意。 Basically, at that time, the average computer had 4 MB of memory, so saving computer memory was quite important.基本上在那个时候,普通电脑有4MB的内存,所以节省电脑内存是相当重要的。 Nowadays we just say "memory is cheap" (quote from Uncle Bob).现在我们只说“内存很便宜”(引用鲍勃叔叔的话)。

Later it turned out that this specialization creates more problems than it is worth.后来事实证明,这种专业化造成的问题多于其价值。

The issue is that the address to one of the elements of such a vector is a complex object (it has to store information on which bit holds which value) compared to regular old-fashioned C-array bool a[] .问题在于,与常规的老式 C 数组bool a[]相比,这种向量的元素之一的地址是一个复杂的对象(它必须存储有关哪个位保存哪个值的信息)。

Since compatibility must be retained, this specialization can't be dropped, but based on that lesson, the same approach was not applied to std::array .由于必须保留兼容性,因此不能放弃此专业化,但根据该课程,相同的方法并未应用于std::array

Another reason is that std::array is supposed to be a C-array wrapper, so it must be as similar to bool a[N] as possible, and must produce the same machine code when used.另一个原因是std::array应该是一个 C 数组包装器,所以它必须尽可能类似于bool a[N] ,并且在使用时必须产生相同的机器代码。

And the last thing, as Cody Gray points out in a comment under question , std::bitset is a constant size array of bits, so such functionality is already available (and can be used if needed).最后一件事,正如 Cody Gray 在问题下的评论中指出的那样, std::bitset是一个恒定大小的位数组,因此此类功能已经可用(并且可以在需要时使用)。

This is a question about history of evolution of C++.这是一个关于 C++ 进化史的问题。 In hindsight a possible explanation is:事后看来,一个可能的解释是:

std::vector<bool> was a mistake. std::vector<bool>是一个错误。 It is a major annoyance that a std::vector<bool> is very different from std::vector<T> .一个主要的烦恼是std::vector<bool>std::vector<T>非常不同。 Generic code that works with vector s often needs a special case for std::vector<bool> .vector一起使用的通用代码通常需要std::vector<bool>的特殊情况。 And users often have to apply weird workarounds like using a std::vector<char> in place of std::vector<bool> .并且用户经常不得不应用奇怪的解决方法,比如使用std::vector<char>代替std::vector<bool> Now we cannot go back without breaking lots of existing code.现在我们不能在不破坏大量现有代码的情况下返回。 With what we know now, maybe std::vector<bool> would never have made it into C++.以我们现在所知道的,也许std::vector<bool>永远不会进入 C++。

std::array was added only in C++11. std::array仅在 C++11 中添加。 There was no reason to make the same mistake again.没有理由再犯同样的错误。

The initial motivation to specialize std::vector for bool was to optimize memory usage.std::vector专门用于bool的最初动机是优化内存使用。

However this was a bad idea as this specialization behaves differently than usual std::vector (see example below).然而,这是一个坏主意,因为这种专业化的行为与通常的std::vector (请参见下面的示例)。

This error was not reproduced later with C++11's std::array这个错误后来没有用 C++11 的std::array重现

#include <array>
#include <vector>

int main()
{
  std::vector<int> i_v(4);
  int i_a = *&i_v[3]; // ok

  std::vector<bool> v(4);
  bool a = *&v[3]; // Compile-time error

  std::array<bool,4> w;
  bool b = *&w[3]; // ok
}

The std::vector<bool> specialization was introduced as early as 1994, as per lib.vector.bool of WG21/N0545 (1) [ emphasis mine]:所述std::vector<bool>专业化引入早在1994年,作为每lib.vector.boolWG21 / N0545 (1)[重点矿山]:

23.1.6 Class vector<bool> [lib.vector.bool] 23.1.6 类vector<bool> [lib.vector.bool]

To optimize space allocation , a specialization for bool is provided: [...]为了优化空间分配,提供了bool的专业化:[...]

with a motivation to optimize for space allocation, a resource that was sparse back then.出于优化空间分配的动机,这是当时稀少的资源。

In retrospect, this turned out to be quite a bad idea, and the original motivation was made moot with the rapid growth of available space in computer hardware.回想起来,结果证明这是一个非常糟糕的主意,随着计算机硬件可用空间的快速增长,最初的动机变得毫无意义。

std::array , on the other hand, was introduced much later, in C++11, alongside eg auto type deduction, a mechanism which highlighted yet another problem with the std::vector<bool> specialization.另一方面, std::array是在 C++11 中引入的,例如auto类型推导,这种机制突出了std::vector<bool>另一个问题。 Naturally the library spec writers did not repeat the same mistake of std::vector<bool> when designing std::array .自然地,库规范编写者在设计std::array时不会重复std::vector<bool>的相同错误。

Eg, the following snippet例如,以下代码段

#include <type_traits>
#include <vector>

int main() {
    std::vector<bool> v{false, false, true, true};
    auto bool_value = v[1];
    static_assert(std::is_same_v<decltype(bool_value), bool>, "");  // Error!
}   

fails with the error message that bool_value is not of type bool , but of the cryptic type (implementation-defined)失败并显示错误消息bool_value不是bool类型,而是神秘类型(实现定义)

 error: static_assert failed due to requirement 'std::is_same_v< std::__1::__bit_reference< std::__1::vector<bool, std::__1::allocator<bool>>, true>, bool>' ""

(1) Working Paper for Draft Proposed International Standard for Information Systems-- Programming Language C++. (1)信息系统国际标准草案的工作文件——编程语言 C++。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM