Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Example program
- #include <exception>
- #include <iostream>
- #include <stdexcept>
- #include <string>
- #include <type_traits>
- #include <vector>
- #define ENABLE_PRINT
- template<typename S, typename T>
- class is_streamable
- {
- template<typename SS, typename TT>
- static auto test(int)
- -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
- template<typename, typename>
- static auto test(...) -> std::false_type;
- public:
- static const bool value = decltype(test<S,T>(0))::value;
- };
- template <typename T> class Stack {
- public:
- using PrintFnc = std::function<std::ostream &(std::ostream &stream, const T &)>;
- T top() {
- if (size() == 0) {
- throw std::runtime_error("Stack is empty");
- }
- return data.back();
- }
- void pop() {
- if (size() != 0) {
- data.erase(data.end() - 1);
- }
- }
- template <typename... Args>
- typename std::enable_if<std::is_constructible<T, Args...>::value, void>::type
- push(Args &&... args) {
- data.emplace_back(args...);
- }
- std::size_t size() const { return data.size(); }
- template <typename U = T, class = typename std::enable_if<is_streamable<std::ostream, U>::value>::type>
- void print() {
- print(data.size());
- }
- template <typename U = T, class = typename std::enable_if<
- is_streamable<std::ostream, U>::value>::type>
- void print(std::size_t elementCount) {
- impl_print(elementCount);
- }
- template <typename U = T, class = typename std::enable_if<!is_streamable<std::ostream, U>::value>::type>
- void print(PrintFnc printFnc) {
- print(data.size(), printFnc);
- }
- template <typename U = T, class = typename std::enable_if<! is_streamable<std::ostream, U>::value>::type>
- void print(std::size_t elementCount, PrintFnc printFnc) {
- impl_print(elementCount, printFnc);
- }
- private:
- std::vector<T> data;
- void impl_print(
- std::size_t elementCount,
- PrintFnc format =
- [](std::ostream &stream, const auto &val) -> std::ostream & {
- return stream << val;
- }) {
- for (auto iter = data.crbegin(); iter < data.crbegin() + elementCount;
- ++iter) {
- format(std::cout, *iter) << std::endl;
- }
- }
- };
- class Test {
- public:
- explicit Test(int a) : a(a), b(a) {}
- Test(int a, int b) : a(a), b(b) {}
- int a, b;
- #ifdef ENABLE_PRINT
- friend std::ostream &operator<<(std::ostream &stream, Test t) {
- return stream << "Test: " << t.a << ", " << t.b;
- }
- #endif
- };
- int main() {
- Stack<Test> stack;
- std::cout << stack.size() << std::endl;
- stack.push(Test(10));
- stack.push(20);
- long test = 1000;
- stack.push(test);
- stack.push(20, 1000);
- try {
- std::cout << stack.size() << std::endl;
- #ifdef ENABLE_PRINT
- stack.print();
- #else
- stack.print([](std::ostream &stream, const Test &t)->std::ostream &{return stream << t.a << " " << t.b;});
- #endif
- } catch (std::exception &e) {
- std::cout << e.what() << std::endl;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement