Skip to main content

xtd::collections::array_list a heterogeneous container supporting multiple types (🟢 Beginner)

How to store any type with a simple xtd collection, and allow them to be easily manipulated.

Simple example​

#include <xtd/xtd>

auto main() -> int {
for (auto item : collections::array_list {"42", 42, 42_s, .42}) {
console::write("{,-8} --> ", item);
if (is<string>(item)) console::write_line("{}", as<string>(item).quoted());
else if (is<int>(item)) console::write_line("0x{:X4}", as<int>(item));
else if (is<time_span>(item)) console::write_line("{} seconds", as<time_span>(item).seconds());
else console::write_line("[{}]", item);
}
}
// This code can produce the following output:
//
// 42 --> "42"
// 42 --> 0x002A
// 00:00:42 --> 42 seconds
// 0.42 --> [0.42]
  • xtd::collections::array_list allows you to store any type.
  • The operator xtd::is easily determines the type of the stored value.
  • The operator xtd::as intuitively converts the stored value into the desired type.
  • No macros or hidden tricks — only modern C++.

Custom types​

Yes, of course you can store your own type in xtd::collections::array_list.

#include <xtd/xtd>

struct foo {
bool operator ==(const foo& f) const noexcept {return value == f.value;}
bool operator <(const foo& f) const noexcept {return value < f.value;}
bool operator >(const foo& f) const noexcept {return value > f.value;}

int value;
};

struct bar : public icomparable<bar>, public iequatable<bar> {
bar() = default;
bar(int value) : value {value} {}

int32 compare_to(const bar& obj) const noexcept override {return value < obj.value ? -1 : value > obj.value ? 1 : 0;}
bool equals(const bar& obj) const noexcept override {return value == obj.value;}

int value;
};

auto main() -> int {
for (auto item : collections::array_list {"42", 42, 42_s, .42, foo {42}, bar {42}}) {
console::write("{,-8} --> ", item);
if (is<string>(item)) console::write_line("{}", as<string>(item).quoted());
else if (is<int>(item)) console::write_line("0x{:X4}", as<int>(item));
else if (is<time_span>(item)) console::write_line("{} seconds", as<time_span>(item).seconds());
else if (is<foo>(item)) console::write_line("f{}", as<foo>(item).value);
else if (is<bar>(item)) console::write_line("b{}", as<bar>(item).value);
else console::write_line("[{}]", item);
}
}
// This code can produce the following output:
//
// 42 --> "42"
// 42 --> 0x002A
// 00:00:42 --> 42 seconds
// 0.42 --> [0.42]
// foo --> f42
// bar --> b42
  • The only constraint is declaring at least the following three operators: ==, < and > as in the example with the foo structure.
  • Or to inherit the interfaces xtd::icomparable and xtd::iequatable as in the example with the structure bar. Indeed, the interface xtd::icomparable automatically creates comparison operators and the interface xtd::iquatable also automatically creates equality and inequality operators.

Conclusion​

Did you know?

There is also a container xtd::collections::hash_table which allows as xtd::collections::array_list to manage a collection of heterogeneous types but sorted on a key that can itself be of different types.

To go further​

See also​