【问题标题】:No class template specialization for array of bool?没有布尔数组的类模板专业化?
【发布时间】:2021-02-27 21:33:33
【问题描述】:

根据https://en.cppreference.com/std::vector<bool> 有一个类模板特化,而std::array<bool, N> 没有。不提供的原因有哪些?

【问题讨论】:

  • 因为std::bitset已经提供了这个。

标签: c++ stdvector template-specialization stdarray class-template


【解决方案1】:

std::vector 被引入时,bool 的特化被认为是一个好主意。基本上,那个时候一般的电脑都有4MB内存,所以节省电脑内存是相当重要的。现在我们只说“内存很便宜”(引自 Bob 大叔)。

后来发现,这种专业化带来的问题多于其价值。

问题在于,与常规的老式 C 数组 bool a[] 相比,此类向量的其中一个元素的地址是一个复杂的对象(它必须存储有关哪个位保存哪个值的信息)。

由于必须保留兼容性,因此不能放弃此专业化,但基于该教训,相同的方法未应用于std::array

另一个原因是std::array应该是一个C数组包装器,所以它必须尽可能与bool a[N]相似,并且在使用时必须产生相同的机器码。

最后一件事,正如 Cody Gray 在 a comment under question 中指出的那样,std::bitset 是一个恒定大小的位数组,因此这样的功能已经可用(并且可以在需要时使用)。

【讨论】:

  • 优秀的答案,+1。但是,请不要对非代码文本使用代码格式:它会干扰其他浏览技术,例如为盲人设计的屏幕阅读器,从而降低网站的可访问性。
【解决方案2】:

这是一个关于 C++ 演变历史的问题。事后看来,一个可能的解释是:

std::vector<bool> 是个错误。 std::vector<bool>std::vector<T> 非常不同,这是一个主要的烦恼。与vectors 一起使用的通用代码通常需要std::vector<bool> 的特殊情况。并且用户经常不得不应用奇怪的变通方法,例如使用std::vector<char> 代替std::vector<bool>。现在我们不能在不破坏大量现有代码的情况下返回。就我们现在所知,std::vector<bool> 可能永远不会进入 C++。

std::array 仅在 C++11 中添加。没有理由再犯同样的错误。

【讨论】:

    【解决方案3】:

    std::vector 专门用于bool 的最初动机是优化内存使用。

    但是这是一个坏主意,因为此专业化的行为与通常的 std::vector 不同(请参见下面的示例)。

    这个错误后来没有用 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
    }
    

    【讨论】:

      【解决方案4】:

      std::vector&lt;bool&gt; 专业化早在 1994 年就引入了,根据 WG21/N0545lib.vector.bool(1) [强调我的]:

      23.1.6 类vector&lt;bool&gt; [lib.vector.bool]

      为了优化空间分配,提供了bool 的特化:[...]

      出于优化空间分配的动机,这是当时稀缺的资源。

      回想起来,这被证明是一个非常糟糕的主意,并且随着计算机硬件可用空间的快速增长,最初的动机变得毫无意义。

      std::array,另一方面,在 C++11 中被引入了很久,例如auto 类型推导,这种机制突出了 std::vector&lt;bool&gt; 专业化的另一个问题。在设计std::array 时,库规范编写者自然不会重复std::vector&lt;bool&gt; 的同样错误。

      例如,下面的sn-p

      #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!
      }   
      

      失败并显示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) 信息系统拟议国际标准草案工作文件——编程语言 C++。

      【讨论】:

        猜你喜欢
        • 2013-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-18
        相关资源
        最近更新 更多