online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
#include <iostream> #include <iterator> #include <sstream> #include <utility> // ============================================== Rudimentary TDD-Support #define SHOW_(expect, ...)\ do {\ std::ostringstream result;\ result.copyfmt(std::cout);\ result << (__VA_ARGS__);\ const bool ok = (result.str() == expect);\ std::cout << (ok ? '*' : '!') << ' '\ << __FUNCTION__ << ':' << __LINE__ << '\t'\ << #__VA_ARGS__ << " --> " << result.str();\ if (!ok) {\ std::cout << " != " << expect;\ }\ std::cout << std::endl;\ }\ while (0) // ======================================================================= #include "my_static_vector.h" void default_ctor_test() { my::static_vector<int, 10> obj1{}; SHOW_("48", sizeof obj1); my::static_vector<double, 3> obj2{}; SHOW_("32", sizeof obj2); } void list_ctor_test() { my::static_vector<int, 5> obj1{5, 9, 12}; SHOW_("5", obj1.at(0)); SHOW_("9", obj1.at(1)); SHOW_("12", obj1.at(2)); } #if 0 void copy_ctor_test() { my::static_vector<int, 5> obj1{5, 9, 12}; my::static_vector<int, 5> obj2{obj1}; SHOW_("5", obj1.at(0)); SHOW_("9", obj1.at(1)); SHOW_("12", obj1.at(2)); SHOW_("5", obj2.at(0)); SHOW_("9", obj2.at(1)); SHOW_("12", obj2.at(2)); } #endif #if 0 void move_ctor_test() { my::static_vector<int, 5> obj1{5, 9, 12}; my::static_vector<int, 5> obj2{std::move(obj1)}; SHOW_("5", obj2.at(0)); SHOW_("9", obj2.at(1)); SHOW_("12", obj2.at(2)); } #endif void max_size_test() { my::static_vector<int, 10> obj1; my::static_vector<double, 3> obj2; SHOW_("10", obj1.max_size()); SHOW_("3", obj2.max_size()); } void size_empty_test() { my::static_vector<int, 10> obj1{}; SHOW_("true", obj1.empty()); SHOW_("0", obj1.size()); obj1.push_back(123); SHOW_("false", obj1.empty()); SHOW_("1", obj1.size()); obj1.push_back(-1); SHOW_("false", obj1.empty()); SHOW_("2", obj1.size()); obj1.pop_back(); SHOW_("false", obj1.empty()); SHOW_("1", obj1.size()); obj1.pop_back(); SHOW_("true", obj1.empty()); SHOW_("0", obj1.size()); } void data_size_test() { using mv = my::static_vector<int, 10>; mv obj1{5, 9, 12}; auto data_test = [](mv::value_type const* d, mv::size_type s) { std::ostringstream os{}; for (;s; --s) { os << *(d++) << ' '; } return os.str(); }; SHOW_("5 9 12 ", data_test(obj1.data(), obj1.size())); } void fast_indexing_test() { my::static_vector<int, 5> obj1{5, 9, 12}; SHOW_("5", obj1[0]); SHOW_("9", obj1[1]); SHOW_("12", obj1[2]); } void safe_indexing_test() { my::static_vector<int, 5> obj1{5, 9, 12}; SHOW_("5", obj1.at(0)); SHOW_("9", obj1.at(1)); SHOW_("12", obj1.at(2)); SHOW_("5", obj1.at(3)); } void resize_clear_test() { my::static_vector<int, 5> obj1{5, 9, 12}; SHOW_("3", obj1.size()); SHOW_("5", obj1.at(0)); SHOW_("9", obj1.at(1)); SHOW_("12", obj1.at(2)); obj1.resize(2); SHOW_("2", obj1.size()); SHOW_("5", obj1.at(0)); SHOW_("9", obj1.at(1)); obj1.resize(4); SHOW_("4", obj1.size()); SHOW_("5", obj1.at(0)); SHOW_("9", obj1.at(1)); SHOW_("0", obj1.at(2)); SHOW_("0", obj1.at(3)); obj1.clear(); SHOW_("0", obj1.size()); } void push_pop_back_test() { my::static_vector<int, 10> obj1{}; obj1.push_back(123); SHOW_("123", obj1.back()); obj1.push_back(-1); SHOW_("-1", obj1.back()); obj1.pop_back(); SHOW_("123", obj1.back()); } #include <string> class NDC { std::string s_; int x_; public: NDC(std::string s, int x) : s_{s}, x_{x} {} std::string to_string() const { return s_ + " " + std::to_string(x_); } }; void emplace_test() { my::static_vector<NDC, 10> obj1{}; SHOW_("0", obj1.size()); obj1.emplace_back("hello", 42); SHOW_("1", obj1.size()); SHOW_("hello 42", obj1.back().to_string()); obj1.emplace_back("whatever", 0); SHOW_("2", obj1.size()); SHOW_("whatever 0", obj1.back().to_string()); } void front_back_test() { my::static_vector<int, 10> obj1{}; obj1.push_back(123); SHOW_("123", obj1.front()); SHOW_("123", obj1.back()); obj1.push_back(-1); SHOW_("123", obj1.front()); SHOW_("-1", obj1.back()); obj1.pop_back(); SHOW_("123", obj1.front()); SHOW_("123", obj1.back()); } #include <iterator> void range_for_test() { std::ostringstream os; my::static_vector<int, 10> obj1{2, 3, 5, 7, 11, 13, 17, 19,}; #if 0 for (auto it = obj1.cbegin(); it != obj1.cend(); ++it) { const auto lfd_nr = (it - obj1.cbegin()) + 1; // const auto lfd_nr = std::distance(obj1.cbegin(), it) + 1; os << lfd_nr << ": " << *it << " -- " } SHOW_("1: 2 -- " "2: 3 -- " "3: 5 -- " "4: 7 -- " "5: 11 -- " "6: 13 -- " "7: 17 -- " "8: 19 -- ", os.str()); #else for (auto const& e : obj1) { os << e << ' '; } SHOW_("2 3 5 7 11 13 17 19 ", os.str()); #endif } #include <algorithm> void algorithm_transform_test() { my::static_vector<int, 10> obj1{2, 3, 5, 7, 11, 13, 17, 19,}; my::static_vector<double, obj1.max_size()> obj2; std::transform(obj1.cbegin(), obj1.cend(), std::back_inserter(obj2), [](decltype(obj2)::value_type e) { return e/2; }); std::ostringstream os; for (const auto &e : obj2) { os << e << ' '; } SHOW_("1 1.5 2.5 3.5 5.5 6.5 8.5 9.5 ", os.str()); } void builtin_transform_test() { using mv = my::static_vector<int, 10>; mv obj1{2, 3, 5, 7, 11, 13, 17, 19,}; auto int_descend_cmp = [](mv::value_type a, mv::value_type b) { return !(a<b); }; // C++11 // [](auto a, auto b) { return !(a<b); }; // C++14 std::ostringstream os; obj1.transform([=](int* f, int* t) { std::sort(f, t, int_descend_cmp); }); for (const auto &e : obj1) { os << e << ' '; } SHOW_("19 17 13 11 7 5 3 2 ", os.str()); } int main() { std::cout.setf(std::ios::boolalpha); #if 1 // move down to include tests from he beginning default_ctor_test(); list_ctor_test(); // copy_ctor_test(); // move_ctor_test(); max_size_test(); size_empty_test(); data_size_test(); fast_indexing_test(); safe_indexing_test(); resize_clear_test(); emplace_test(); push_pop_back_test(); front_back_test(); range_for_test(); algorithm_transform_test(); builtin_transform_test(); #endif // move up to include tests from the end std::cout << "*** TESTING COMPLETED ***" << std::endl; }
#ifndef MY_STATIC_VECTOR_H #define MY_STATIC_VECTOR_H #include <cassert> #include <initializer_list> #include <type_traits> namespace my { /* * A class much like `std::vector` but with pre-allocated space * in a maximum size. As for `std::vector` this container is empty * at the beginning. Need to be added before they can be accessed. */ template <typename T, std::size_t N> class static_vector { public: using value_type = T; using size_type = decltype(N); // c'tors, d'tors and assignment static_vector(std::initializer_list<value_type> const& init) : static_vector{} { assert(init.size() <= max_size()); // check "breach of contract" for (auto &e : init) { if (size() == max_size()) break; // <------ for "robustness" push_back(e); } } ~static_vector() { clear(); } static_vector() =default; static_vector(const static_vector&) =delete; static_vector(static_vector&&) =delete; static_vector& operator=(const static_vector&) =delete; static_vector& operator=(static_vector&&) =delete; static constexpr size_type max_size() { return N; } size_type size() const { assert_in_bounds(); return filled_ - reinterpret_cast<value_type const*>(raw_data_); } bool empty() const { return (size() == 0); } value_type* data() { return reinterpret_cast<value_type*>(raw_data_); } value_type const* data() const { return reinterpret_cast<const value_type*>(raw_data_); } value_type& front() { assert_not_empty(); return reinterpret_cast<value_type*>(raw_data_)[0]; } value_type const& front() const { assert_not_empty(); return reinterpret_cast<const value_type*>(raw_data_)[0]; } value_type& back() { assert_not_empty(); return filled_[-1]; } value_type const& back() const { assert_not_empty(); return filled_[-1]; } // mimicking the behavior of `std::vector` the index operator as // implemented below causes undefined behavior for out of bounds // indices value_type& operator[](size_type index) { assert_in_bounds(); return reinterpret_cast<value_type*>(raw_data_)[index]; } value_type const& operator[](size_type index) const { assert_in_bounds(); return reinterpret_cast<const value_type*>(raw_data_)[index]; } // mimicking the behavior of vectors `at` should NOT cause undefined // behavior (contrary to `operator[]` which may do so) but the proposed // solution is not REALLY a good one; though without exceptions there // is not much wigleroom for somehow "curing" the problem as any // solution chosen will have a tendency to cover up a problem that // would have better be detected earlier ... value_type& at(size_type index) { assert_not_empty(); return reinterpret_cast<value_type*>(raw_data_)[index % size()]; } value_type const& at(size_type index) const { assert_not_empty(); return reinterpret_cast<const value_type*>(raw_data_)[index % size()]; } void push_back(T const& item_to_append) { assert_not_full(); *(filled_++) = item_to_append; assert_not_empty(); } void pop_back() { assert_not_empty(); (--filled_)->~T(); assert_not_full(); } template<typename ...Ts> void emplace_back(Ts&& ...ctor_args) { assert_not_full(); new (filled_++) value_type{std::forward<Ts>(ctor_args)...}; assert_not_empty(); } void resize(size_type new_size); void clear() { while (!empty()) { pop_back(); } } // providing iterators (we can simply use pointers here) using iterator = value_type*; using const_iterator = value_type const*; iterator begin() { return reinterpret_cast<value_type*>(raw_data_); } iterator end() { return filled_; } const_iterator begin() const { return reinterpret_cast<const value_type*>(raw_data_); } const_iterator end() const { return filled_; } const_iterator cbegin() const { return reinterpret_cast<const value_type*>(raw_data_); } const_iterator cend() const { return filled_; } template<typename F> void transform(F func) { func(reinterpret_cast<value_type*>(raw_data_), filled_); } private: // assertions for early error detection in unit tests // do NOT call public member functions here EXCEPT size() // so that the below may used freely; void assert_in_bounds() const { assert(filled_ >= reinterpret_cast<value_type const*>(raw_data_)); assert(filled_ <= reinterpret_cast<value_type const*>(raw_data_) + N); } void assert_not_empty() const { assert(size() > 0); } void assert_not_full() const { assert(size() < max_size()); } using storage_type = typename std::aligned_storage<sizeof(T), alignof(T)>::type; storage_type raw_data_[N]; value_type* filled_{reinterpret_cast<value_type*>(raw_data_)}; }; template<typename T, std::size_t N> void static_vector<T, N>::resize(size_type new_size) { static_assert(std::is_unsigned<size_type>::value, "for signed value_type also `assert(new_size < 0)`"); assert(new_size <= max_size()); while (size() < new_size) { emplace_back(); } while (size() > new_size) { pop_back(); } } } // namespace #endif // include guard

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue