mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-21 19:30:03 +02:00
WIP
This commit is contained in:
parent
c36dfc3992
commit
8e2494729b
@ -4,176 +4,133 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "TypeTraits.h"
|
||||||
|
|
||||||
namespace sls {
|
namespace sls {
|
||||||
template <typename T, size_t Capacity> class FixedCapacityContainer {
|
template <typename T, size_t Capacity> class FixedCapacityContainer {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using size_type = typename std::array<T, Capacity>::size_type;
|
||||||
|
using value_type = typename std::array<T, Capacity>::value_type;
|
||||||
|
using iterator = typename std::array<T, Capacity>::iterator;
|
||||||
|
using const_iterator = typename std::array<T, Capacity>::const_iterator;
|
||||||
|
|
||||||
FixedCapacityContainer() = default;
|
FixedCapacityContainer() = default;
|
||||||
explicit FixedCapacityContainer(std::initializer_list<T> l);
|
explicit FixedCapacityContainer(std::initializer_list<T> l) {
|
||||||
explicit FixedCapacityContainer(const std::vector<T> &v);
|
current_size = l.size();
|
||||||
|
std::copy(l.begin(), l.end(), data_.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V,
|
||||||
|
typename = typename std::enable_if<
|
||||||
|
is_light_container<V>::value &&
|
||||||
|
std::is_same<T, typename V::value_type>::value>::type>
|
||||||
|
explicit FixedCapacityContainer(const V &v) {
|
||||||
|
if (v.size() > Capacity) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Capacity needs to be same size or larger than vector");
|
||||||
|
}
|
||||||
|
current_size = v.size();
|
||||||
|
std::copy(v.begin(), v.end(), data_.begin());
|
||||||
|
}
|
||||||
|
|
||||||
template <size_t OtherCapacity>
|
template <size_t OtherCapacity>
|
||||||
explicit FixedCapacityContainer(
|
explicit FixedCapacityContainer(
|
||||||
const FixedCapacityContainer<T, OtherCapacity> &other) noexcept;
|
const FixedCapacityContainer<T, OtherCapacity> &other) noexcept {
|
||||||
|
static_assert(Capacity >= OtherCapacity,
|
||||||
|
"Container needs to be same size or larger");
|
||||||
|
current_size = other.size();
|
||||||
|
std::copy(other.cbegin(), other.cend(), data_.begin());
|
||||||
|
}
|
||||||
|
|
||||||
FixedCapacityContainer &operator=(const std::vector<T> &other);
|
FixedCapacityContainer &operator=(const std::vector<T> &other) {
|
||||||
|
std::copy(other.begin(), other.end(), data_.begin());
|
||||||
|
current_size = other.size();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const std::vector<T> &other) const noexcept;
|
/** Compare FixedCapacityContainer with any other container*/
|
||||||
bool operator!=(const std::vector<T> &other) const noexcept;
|
template <typename V>
|
||||||
|
typename std::enable_if<is_container<V>::value, bool>::type
|
||||||
|
operator==(const V &other) const noexcept {
|
||||||
|
if (current_size != other.size()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i != current_size; ++i) {
|
||||||
|
if (data_[i] != other[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
operator std::vector<T>(){return std::vector<T>(begin(), end());}
|
template <typename V>
|
||||||
|
typename std::enable_if<is_container<V>::value, bool>::type
|
||||||
|
operator!=(const V &other) const noexcept {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
template <size_t OtherCapacity>
|
operator std::vector<T>() { return std::vector<T>(begin(), end()); }
|
||||||
bool operator==(const FixedCapacityContainer<T, OtherCapacity> &other) const
|
|
||||||
noexcept;
|
|
||||||
|
|
||||||
template <size_t OtherCapacity>
|
|
||||||
bool operator!=(const FixedCapacityContainer<T, OtherCapacity> &other) const
|
|
||||||
noexcept;
|
|
||||||
|
|
||||||
T &operator[](size_t i) { return data_[i]; }
|
T &operator[](size_t i) { return data_[i]; }
|
||||||
const T &operator[](size_t i) const { return data_[i]; }
|
const T &operator[](size_t i) const { return data_[i]; }
|
||||||
|
constexpr size_type size() const noexcept { return current_size; }
|
||||||
constexpr size_t size() const noexcept { return size_; }
|
bool empty() const noexcept { return current_size == 0; }
|
||||||
bool empty() const noexcept { return size_ == 0; }
|
|
||||||
constexpr size_t capacity() const noexcept { return Capacity; }
|
constexpr size_t capacity() const noexcept { return Capacity; }
|
||||||
|
|
||||||
void push_back(const T &value);
|
void push_back(const T &value) {
|
||||||
void resize(size_t new_size);
|
if (current_size == Capacity) {
|
||||||
void erase(T *ptr);
|
throw std::runtime_error("Container is full");
|
||||||
|
} else {
|
||||||
|
data_[current_size] = value;
|
||||||
|
++current_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(size_t new_size) {
|
||||||
|
if (new_size > Capacity) {
|
||||||
|
throw std::runtime_error("Cannot resize beyond capacity");
|
||||||
|
} else {
|
||||||
|
current_size = new_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(T *ptr) {
|
||||||
|
if (ptr >= begin() && ptr < end()) {
|
||||||
|
current_size = static_cast<size_t>(ptr - begin());
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("tried to erase with a ptr outside obj");
|
||||||
|
}
|
||||||
|
}
|
||||||
T &front() noexcept { return data_.front(); }
|
T &front() noexcept { return data_.front(); }
|
||||||
T &back() noexcept { return data_[size_ - 1]; }
|
T &back() noexcept { return data_[current_size - 1]; }
|
||||||
constexpr const T &front() const noexcept { return data_.front(); }
|
constexpr const T &front() const noexcept { return data_.front(); }
|
||||||
constexpr const T &back() const noexcept { return data_[size_ - 1]; }
|
constexpr const T &back() const noexcept { return data_[current_size - 1]; }
|
||||||
|
|
||||||
// iterators
|
// iterators
|
||||||
T *begin() noexcept { return &data_[0]; }
|
iterator begin() noexcept { return data_.begin(); }
|
||||||
T *end() noexcept { return &data_[size_]; }
|
const_iterator begin() const noexcept { return data_.begin(); }
|
||||||
const T *cbegin() const noexcept { return &data_[0]; }
|
iterator end() noexcept { return &data_[current_size]; }
|
||||||
const T *cend() const noexcept { return &data_[size_]; }
|
const_iterator end() const noexcept { return &data_[current_size]; }
|
||||||
|
const_iterator cbegin() const noexcept { return data_.cbegin(); }
|
||||||
|
const_iterator cend() const noexcept { return &data_[current_size]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t size_{0};
|
size_type current_size{};
|
||||||
std::array<T, Capacity> data_;
|
std::array<T, Capacity> data_;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* Member functions */
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
FixedCapacityContainer<T, Capacity>::FixedCapacityContainer(
|
|
||||||
std::initializer_list<T> l) {
|
|
||||||
size_ = l.size();
|
|
||||||
std::copy(l.begin(), l.end(), data_.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
FixedCapacityContainer<T, Capacity>::FixedCapacityContainer(
|
|
||||||
const std::vector<T> &v) {
|
|
||||||
if (v.size() > Capacity) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"Capacity needs to be same size or larger than vector");
|
|
||||||
}
|
|
||||||
size_ = v.size();
|
|
||||||
std::copy(v.begin(), v.end(), data_.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
template <size_t OtherCapacity>
|
|
||||||
FixedCapacityContainer<T, Capacity>::FixedCapacityContainer(
|
|
||||||
const FixedCapacityContainer<T, OtherCapacity> &other) noexcept {
|
|
||||||
static_assert(Capacity >= OtherCapacity,
|
|
||||||
"Container needs to be same size or larger");
|
|
||||||
size_ = other.size();
|
|
||||||
std::copy(other.cbegin(), other.cend(), data_.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
void FixedCapacityContainer<T, Capacity>::push_back(const T &value) {
|
|
||||||
if (size_ == Capacity) {
|
|
||||||
throw std::runtime_error("Container is full");
|
|
||||||
} else {
|
|
||||||
data_[size_] = value;
|
|
||||||
++size_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
void FixedCapacityContainer<T, Capacity>::resize(size_t new_size) {
|
|
||||||
if (new_size > Capacity) {
|
|
||||||
throw std::runtime_error("Cannot resize beyond capacity");
|
|
||||||
} else {
|
|
||||||
size_ = new_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
FixedCapacityContainer<T, Capacity> &FixedCapacityContainer<T, Capacity>::
|
|
||||||
operator=(const std::vector<T> &other) {
|
|
||||||
std::copy(other.begin(), other.end(), data_.begin());
|
|
||||||
size_ = other.size();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
bool FixedCapacityContainer<T, Capacity>::
|
|
||||||
operator==(const std::vector<T> &other) const noexcept {
|
|
||||||
if (size_ != other.size()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
for (size_t i = 0; i != size_; ++i) {
|
|
||||||
if (data_[i] != other[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
bool FixedCapacityContainer<T, Capacity>::
|
|
||||||
operator!=(const std::vector<T> &other) const noexcept {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
template <size_t OtherCapacity>
|
|
||||||
bool FixedCapacityContainer<T, Capacity>::
|
|
||||||
operator==(const FixedCapacityContainer<T, OtherCapacity> &other) const
|
|
||||||
noexcept {
|
|
||||||
if (size_ != other.size()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
for (size_t i = 0; i != size_; ++i) {
|
|
||||||
if (data_[i] != other[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
template <size_t OtherCapacity>
|
|
||||||
bool FixedCapacityContainer<T, Capacity>::
|
|
||||||
operator!=(const FixedCapacityContainer<T, OtherCapacity> &other) const
|
|
||||||
noexcept {
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
|
||||||
void FixedCapacityContainer<T, Capacity>::erase(T *ptr) {
|
|
||||||
if (ptr >= begin() && ptr < end()) {
|
|
||||||
size_ = static_cast<size_t>(ptr - begin());
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error("tried to erase with a ptr outside obj");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free function concerning FixedCapacityContainer */
|
/* Free function concerning FixedCapacityContainer */
|
||||||
template <typename T, size_t Capacity>
|
template <typename T, size_t Capacity>
|
||||||
constexpr T *begin(FixedCapacityContainer<T, Capacity> &container) noexcept {
|
typename FixedCapacityContainer<T, Capacity>::iterator
|
||||||
|
begin(FixedCapacityContainer<T, Capacity> &container) noexcept {
|
||||||
return container.begin();
|
return container.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, size_t Capacity>
|
template <typename T, size_t Capacity>
|
||||||
constexpr T *end(FixedCapacityContainer<T, Capacity> &container) noexcept {
|
typename FixedCapacityContainer<T, Capacity>::iterator
|
||||||
|
end(FixedCapacityContainer<T, Capacity> &container) noexcept {
|
||||||
return container.end();
|
return container.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,4 +137,11 @@ template <typename T> T StringTo(std::string t) {
|
|||||||
return StringTo<T>(t, unit);
|
return StringTo<T>(t, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** For types with a .str() method use this for conversion */
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<has_str<T>::value, std::string>::type
|
||||||
|
ToString(const T &obj) {
|
||||||
|
return obj.str();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sls
|
} // namespace sls
|
||||||
|
@ -58,4 +58,25 @@ struct is_container<
|
|||||||
decltype(std::declval<T>().empty())>,
|
decltype(std::declval<T>().empty())>,
|
||||||
void>::type> : public std::true_type {};
|
void>::type> : public std::true_type {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type trait to evaluate if template parameter is
|
||||||
|
* complying with a standard container
|
||||||
|
*/
|
||||||
|
template <typename T, typename _ = void>
|
||||||
|
struct is_light_container : std::false_type {};
|
||||||
|
|
||||||
|
template <typename... Ts> struct is_light_container_helper {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_light_container<
|
||||||
|
T, typename std::conditional<
|
||||||
|
false,
|
||||||
|
is_container_helper<typename T::value_type, typename T::size_type,
|
||||||
|
typename T::iterator, typename T::const_iterator,
|
||||||
|
decltype(std::declval<T>().size()),
|
||||||
|
decltype(std::declval<T>().begin()),
|
||||||
|
decltype(std::declval<T>().end())>,
|
||||||
|
void>::type> : public std::true_type {};
|
||||||
|
|
||||||
} // namespace sls
|
} // namespace sls
|
@ -1,8 +1,28 @@
|
|||||||
#include "FixedCapacityContainer.h"
|
#include "FixedCapacityContainer.h"
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
#include "TypeTraits.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
using sls::FixedCapacityContainer;
|
using sls::FixedCapacityContainer;
|
||||||
|
|
||||||
|
TEST_CASE("FixedCapacityContainer is a container"){
|
||||||
|
REQUIRE(sls::is_container<FixedCapacityContainer<int,7>>::value == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("Construct from vector"){
|
||||||
|
std::vector<int> vec{1,2,3};
|
||||||
|
FixedCapacityContainer<int, 5> fcc{vec};
|
||||||
|
REQUIRE(fcc == vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Construct from array"){
|
||||||
|
std::array<int,3> arr{1,2,3};
|
||||||
|
FixedCapacityContainer<int, 5> fcc{arr};
|
||||||
|
REQUIRE(fcc == arr);
|
||||||
|
}
|
||||||
|
|
||||||
SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") {
|
SCENARIO("FixedCapacityContainers can be sized and resized", "[support]") {
|
||||||
|
|
||||||
GIVEN("A default constructed container") {
|
GIVEN("A default constructed container") {
|
||||||
|
@ -1,27 +1,25 @@
|
|||||||
#include "TimeHelper.h"
|
#include "TimeHelper.h"
|
||||||
#include "ToString.h"
|
#include "ToString.h"
|
||||||
|
#include "network_utils.h"
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
// using namespace sls;
|
// using namespace sls;
|
||||||
using sls::ToString;
|
|
||||||
using sls::StringTo;
|
using sls::StringTo;
|
||||||
|
using sls::ToString;
|
||||||
using namespace sls::time;
|
using namespace sls::time;
|
||||||
|
|
||||||
|
TEST_CASE("Integer conversions", "[support]") {
|
||||||
TEST_CASE("Integer conversions", "[support]"){
|
|
||||||
REQUIRE(ToString(0) == "0");
|
REQUIRE(ToString(0) == "0");
|
||||||
REQUIRE(ToString(1) == "1");
|
REQUIRE(ToString(1) == "1");
|
||||||
REQUIRE(ToString(-1) == "-1");
|
REQUIRE(ToString(-1) == "-1");
|
||||||
REQUIRE(ToString(100) == "100");
|
REQUIRE(ToString(100) == "100");
|
||||||
REQUIRE(ToString(589633100) == "589633100");
|
REQUIRE(ToString(589633100) == "589633100");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("floating point conversions", "[support]"){
|
TEST_CASE("floating point conversions", "[support]") {
|
||||||
//Should strip trailing zeros
|
// Should strip trailing zeros
|
||||||
REQUIRE(ToString(0.) == "0");
|
REQUIRE(ToString(0.) == "0");
|
||||||
REQUIRE(ToString(1.) == "1");
|
REQUIRE(ToString(1.) == "1");
|
||||||
REQUIRE(ToString(-1.) == "-1");
|
REQUIRE(ToString(-1.) == "-1");
|
||||||
@ -32,7 +30,6 @@ TEST_CASE("floating point conversions", "[support]"){
|
|||||||
REQUIRE(ToString(2.35010) == "2.3501");
|
REQUIRE(ToString(2.35010) == "2.3501");
|
||||||
REQUIRE(ToString(5000) == "5000");
|
REQUIRE(ToString(5000) == "5000");
|
||||||
REQUIRE(ToString(5E15) == "5000000000000000");
|
REQUIRE(ToString(5E15) == "5000000000000000");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("conversion from duration to string", "[support]") {
|
TEST_CASE("conversion from duration to string", "[support]") {
|
||||||
@ -55,13 +52,13 @@ TEST_CASE("string to std::chrono::duration", "[support]") {
|
|||||||
REQUIRE_THROWS(StringTo<ns>("asvn"));
|
REQUIRE_THROWS(StringTo<ns>("asvn"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Convert vector of time", "[support]"){
|
TEST_CASE("Convert vector of time", "[support]") {
|
||||||
std::vector<ns> vec{ns(150), us(10), ns(600)};
|
std::vector<ns> vec{ns(150), us(10), ns(600)};
|
||||||
REQUIRE(ToString(vec) == "[150ns, 10us, 600ns]");
|
REQUIRE(ToString(vec) == "[150ns, 10us, 600ns]");
|
||||||
REQUIRE(ToString(vec, "ns") == "[150ns, 10000ns, 600ns]");
|
REQUIRE(ToString(vec, "ns") == "[150ns, 10000ns, 600ns]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Vector of int", "[support]"){
|
TEST_CASE("Vector of int", "[support]") {
|
||||||
std::vector<int> vec;
|
std::vector<int> vec;
|
||||||
REQUIRE(ToString(vec) == "[]");
|
REQUIRE(ToString(vec) == "[]");
|
||||||
|
|
||||||
@ -73,10 +70,9 @@ TEST_CASE("Vector of int", "[support]"){
|
|||||||
|
|
||||||
vec.push_back(5000);
|
vec.push_back(5000);
|
||||||
REQUIRE(ToString(vec) == "[1, 172, 5000]");
|
REQUIRE(ToString(vec) == "[1, 172, 5000]");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Vector of double", "[support]"){
|
TEST_CASE("Vector of double", "[support]") {
|
||||||
std::vector<double> vec;
|
std::vector<double> vec;
|
||||||
REQUIRE(ToString(vec) == "[]");
|
REQUIRE(ToString(vec) == "[]");
|
||||||
|
|
||||||
@ -90,8 +86,13 @@ TEST_CASE("Vector of double", "[support]"){
|
|||||||
REQUIRE(ToString(vec) == "[1.3, 5669.325, -5669.325005]");
|
REQUIRE(ToString(vec) == "[1.3, 5669.325, -5669.325005]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Array"){
|
TEST_CASE("Array") {
|
||||||
std::array<int, 3> arr{1,2,3};
|
std::array<int, 3> arr{1, 2, 3};
|
||||||
REQUIRE(ToString(arr) == "[1, 2, 3]");
|
REQUIRE(ToString(arr) == "[1, 2, 3]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Convert types with str method"){
|
||||||
|
sls::IpAddr addr;
|
||||||
|
REQUIRE(ToString(addr) == "0.0.0.0");
|
||||||
|
REQUIRE(ToString(sls::IpAddr{}) == "0.0.0.0");
|
||||||
}
|
}
|
@ -4,6 +4,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
//Dummy classes only used here for testing
|
//Dummy classes only used here for testing
|
||||||
class DummyWithStr {
|
class DummyWithStr {
|
||||||
@ -39,3 +40,7 @@ TEST_CASE("sls::is_duration"){
|
|||||||
REQUIRE(sls::is_duration<int>::value == false);
|
REQUIRE(sls::is_duration<int>::value == false);
|
||||||
REQUIRE(sls::is_duration<std::vector<int>>::value == false);
|
REQUIRE(sls::is_duration<std::vector<int>>::value == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("initializer list"){
|
||||||
|
REQUIRE(sls::is_light_container<std::initializer_list<int>>::value == true);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user