std::vector<>
.vector<>
in their examples, badlyvector<>
is very well specified, most APIs are notvector<>
has been very well vetted, so it is extremely unlikely the candidate will find a bugstd::vector<>
std::vector<bool>
specialization0100
mean?void f() {
int i; // the value of i has no meaning
}
vector
is a container, the standard includes a table of the container requirements:template <class T>
void test_equality_1(const T& a, const T& b, const T& c) {
REQUIRE(a == a); // Reflexivity
REQUIRE(!(a == b) || (b == a)); // Symmetry
REQUIRE(!(a == b && b == c) || (a == c)); // Transitivity
}
{
vector<int> a, b, c;
test_equality_1(a, b, c);
}
operator==()
could always return truetemplate <class T>
auto make_vector(initializer_list<T> init, std::size_t additional_capacity) {
vector<T> r;
r.reserve(size(init) + additional_capacity);
r.insert(end(r), init);
return r;
}
struct {
int tag;
std::vector<int> value;
} vec_rep[]{
{0, make_vector<int>({}, 0)}, {0, make_vector<int>({}, 1)},
{0, make_vector<int>({}, 2)},
{1, make_vector({0}, 0)}, {1, make_vector({0}, 1)},
{1, make_vector({0}, 2)},
{2, make_vector({0, 1}, 0)}, {2, make_vector({0, 1}, 0)},
{2, make_vector({0, 1}, 0)},
{3, make_vector({0, 2}, 0)}, {3, make_vector({0, 2}, 0)},
{3, make_vector({0, 2}, 0)},
{4, make_vector({1, 2}, 0)}, {4, make_vector({1, 2}, 0)},
{4, make_vector({1, 2}, 0)},
};
template <class T>
void test_equality_2(const T& a) {
// Reflexivity
for (const auto& e : a)
REQUIRE(e.value == e.value);
// Symmetry
for_each_k_combination<2>(a, [](const auto& a, const auto& b) {
REQUIRE((a.tag == b.tag) == (a.value == b.value));
REQUIRE((a.tag == b.tag) == (b.value == a.value));
});
// Transitivity
for_each_k_combination<3>(a, [](const auto& a, const auto& b, const auto& c) {
REQUIRE(!(a.value == b.value && b.value == c.value) ||
(a.value == c.value));
});
}
{
test_equality_2(vec_rep);
}
for_each_k_combination<>
is an interesting algorithm (implementation in my notes){
int a[] = {0, 1, 2, 3, 4};
for_each_k_combination<3>(a, [](int a, int b, int c){
cout << a << "," << b << "," << c << endl;
});
}
operator==()
is correct we can test operator operator!=()
easilytemplate <class T>
void test_inequality_1(const T& a) {
for_each_k_combination<2>(a, [](const auto& a, const auto& b){
REQUIRE(!(a.value == b.value) == (a.value != b.value));
REQUIRE(!(a.value == b.value) == (b.value != a.value));
});
}
{
test_inequality_1(vec_rep);
}
Let m() be an an action that modifies its argument such that given a=b, m(a)⟹a≠b.
a→b⟹a=b.Let a=c. a→b, m(a)⟹a≠b∧b=c.
vector<int> a;
vector<int> b = a;
a.push_back(42);
assert(b.back() == 42);
template <class T>
void test_copy_and_assignment_1(const T& v) {
for (const auto& a : v) {
{
decltype(a.value) b = a.value; // copy construct
REQUIRE(a.value == b);
}
{
decltype(a.value) b; // default construct
b = a.value; // assignment
REQUIRE(a.value == b);
}
}
}
{
test_copy_and_assignment_1(vec_rep);
}
std::vector<int> vec_rep_2[]{
make_vector<int>({}, 0),
make_vector<int>({}, 1),
make_vector<int>({}, 2),
make_vector({0}, 0),
make_vector({0}, 1),
make_vector({0}, 2),
make_vector({0, 1}, 0),
make_vector({0, 2}, 0),
make_vector({1, 2}, 0)
};
template <class T>
void modify(vector<T>& a) {
a.push_back(T{});
}
template <class T>
void test_copy_and_assignment_2(const T& v) {
for (const auto& a : v) {
decltype(a) b = a; // copy construct
REQUIRE(a == b); // copies are equal
b = b; // self assignment
REQUIRE(a == b); // self assignment is a no-op
modify(b);
REQUIRE(a != b); // copies are disjoint
}
for (const auto& a : v) {
for (const auto& c : v) {
decltype(a) b = a; // make a copy
b = c; // copy assignment
REQUIRE(b == c); // copies ar equal
modify(b);
REQUIRE(b != c); // copies are disjoint
}
}
}
vector
: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdfContainer
and EqualityComparable
look those up as welloperato==()
which fails in various ways and test itfor_each_k_combination<>
is available here https://github.com/sean-parent/notebook/blob/master/common.hppvector<T>
where T
is not EqualityComparable
?