众所周知,与主模板相比,vector<bool>
它具有非通用接口vector<T>
。
相关的区别在于嵌套类型reference
andconst_reference
是typedef
forT&
和T const&
在一般情况下,以及代理类 reference
和值类型 bool
for vector<bool>
。
在访问向量元素时,记住向量对象的常量性决定了 areference
或const_reference
是否由 . 返回也很重要operator[]
。此外,auto
将删除参考限定符,而decltype
将保留那些。
让我们看一下 / 的非 const / const 向量bool
,int
并使用auto
, decltype(auto)
and auto const&
(显然auto&
会导致代理的实时问题)。您会得到以下行为:
#include <vector>
#include <type_traits>
#include <typeinfo>
#include <iostream>
#include <ios>
int main() {
using namespace std;
vector<bool> vb = { true, false, true, false };
vector<int > vi = { 1, 0, 1, 0 };
auto vb2 = vb[2]; // vector<bool>::reference != bool
auto vi2 = vi[2]; // int
decltype(auto) rvb2 = vb[2]; // vector<bool>::reference
decltype(auto) rvi2 = vi[2]; // int&
auto const& crvb2 = vb[2]; // vector<bool>::reference const& != bool const&
auto const& crvi2 = vi[2]; // int const&
auto ovb2 = vb2;
ovb2 = false; // OOPS ovb2 has reference semantics
cout << boolalpha << (vb[2] == true) << "\n";
auto ovi2 = vi2;
ovi2 = 0; // OK, ovi2 has value semantics
cout << boolalpha << (vi[2] == 1) << "\n";
static_assert(is_convertible<decltype(vb2), vector<bool>::value_type>::value, "");
static_assert(is_same <decltype(vi2), vector<int >::value_type>::value, "");
static_assert(is_same <decltype(rvb2), vector<bool>::reference>::value, "");
static_assert(is_same <decltype(rvi2), vector<int >::reference>::value, "");
static_assert(is_convertible<decltype(crvb2), vector<bool>::const_reference>::value, "");
static_assert(is_same <decltype(crvi2), vector<int >::const_reference>::value, "");
vector<bool> const cvb = { true, false, true, false };
vector<int > const cvi = { 1, 0, 1, 0 };
auto cvb2 = cvb[2]; // vector<bool>::const_reference == bool
auto cvi2 = cvi[2]; // int
decltype(auto) rcvb2 = cvb[2]; // vector<bool>::const_reference == bool
decltype(auto) rcvi2 = cvi[2]; // int const&
auto const& crcvb2 = cvb[2]; // vector<bool>::reference const& != bool const&
auto const& crcvi2 = cvi[2]; // int const&
static_assert(is_same <decltype(cvb2), vector<bool>::value_type>::value, "");
static_assert(is_same <decltype(cvi2), vector<int >::value_type>::value, "");
static_assert(is_same <decltype(rcvb2), vector<bool>::const_reference>::value, "");
static_assert(is_same <decltype(rcvi2), vector<int >::const_reference>::value, "");
static_assert(is_convertible<decltype(crcvb2), vector<bool>::const_reference>::value, "");
static_assert(is_same <decltype(crcvi2), vector<int >::const_reference>::value, "");
auto ocvb2 = cvb2;
ocvb2 = false; // OK, ocvb2 has value semantics
cout << boolalpha << (cvb[2] == true) << "\n";
auto ocvi2 = cvi2;
ocvi2 = 0; // OK, ocvi2 has value semantics
cout << boolalpha << (cvi[2] == 1) << "\n";
}
现场示例
请注意,对于非常量vector<bool>
,使用auto
onoperator[]
将为您提供没有值语义的引用代理。使用 aconst vector<bool>
将避免这种情况。我看不出如何以任何其他方式解决这个问题。
Theauto const&
在行为上是等效的,is_convertible
但is_same
在static_assert
. 我认为这是最好的。
请注意,对于代理容器上的一般迭代和 STL 算法,情况并没有那么暗淡。请参阅Hinnant 的专栏。