From 30c1f856d469d181b2c8520e7c1361e436f559bf Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Thu, 29 Aug 2019 21:45:01 -0400 Subject: See if C++11 features work --- libtests/build.mk | 1 + libtests/cxx11.cc | 303 ++++++++++++++++++++++++++++++++++++++++++++++ libtests/qtest/cxx11.test | 16 +++ 3 files changed, 320 insertions(+) create mode 100644 libtests/cxx11.cc create mode 100644 libtests/qtest/cxx11.test (limited to 'libtests') diff --git a/libtests/build.mk b/libtests/build.mk index c8cc4d83..8eea8d2d 100644 --- a/libtests/build.mk +++ b/libtests/build.mk @@ -1,4 +1,5 @@ BINS_libtests = \ + cxx11 \ aes \ ascii85 \ bits \ diff --git a/libtests/cxx11.cc b/libtests/cxx11.cc new file mode 100644 index 00000000..692efcec --- /dev/null +++ b/libtests/cxx11.cc @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +// Functional programming + +// Function that returns a callable in the form of a lambda +std::function make_adder(int x) +{ + return ([=](int a) -> int{ return x + a; }); +} + +void do_functional() +{ + // Lambda with no capture + auto simple_lambda = [](int a){ return a + 3; }; + assert(simple_lambda(5) == 8); + + // Capture by value + int x = 5; + auto by_value = [x](int a){ return a + x; }; + assert(by_value(1) == 6); + x = 7; // change not seen by lambda + assert(by_value(1) == 6); + // Also >> at end of template + assert((std::is_convertible>::value)); + + // Capture by reference + auto by_reference = [&x](int a){ return a + x; }; + assert(by_reference(1) == 8); + x = 8; // change seen my lambda + assert(by_reference(1) == 9); + + // Get a callable from a function + auto add3 = make_adder(3); + assert(add3(5) == 8); + + auto make_addr_lambda = [](int a) { + return [a](int b) { return a + b; }; + }; + + assert(make_addr_lambda(6)(8) == 14); +} + +// Integer types, type traits + +template +void check_size(size_t size, bool is_signed) +{ + assert(sizeof(T) == size); + assert(std::is_signed::value == is_signed); +} + +void do_inttypes() +{ + // static_assert is a compile-time check + static_assert(1 == sizeof(int8_t), "int8_t check"); + check_size(1, true); + check_size(1, false); + check_size(2, true); + check_size(2, false); + check_size(4, true); + check_size(4, false); + check_size(8, true); + check_size(8, false); + + // auto, decltype + auto x = 5LL; + check_size(8, true); + assert((std::is_same::value)); +} + +class A +{ + public: + static constexpr auto def_value = 5; + A(int x) : + x(x) + { + } + // Constructor delegation + A() : A(def_value) + { + } + int getX() const + { + return x; + } + + private: + int x; +}; + +void do_iteration() +{ + // Initializers, foreach syntax, auto for iterators + std::vector v = { 1, 2, 3, 4 }; + assert(v.size() == 4); + int sum = 0; + for (auto i: v) + { + sum += i; + } + assert(10 == sum); + for (auto i = v.begin(); i != v.end(); ++i) + { + sum += *i; + } + assert(20 == sum); + + std::vector v2 = { A(), A(3) }; + assert(5 == v2.at(0).getX()); + assert(3 == v2.at(1).getX()); +} + +// Variadic template + +template +void variadic1(A1 const& a1) +{ + assert(a1 == 12); +} + +template +void variadic1(A1 const& a1, A2 const& a2) +{ + assert(a1 == a2); +} + +template +void variadic(Args... args) +{ + variadic1(args...); +} + +template +bool pairwise_equal(A const& a, A const& b) +{ + return (a == b); +} + +template +bool pairwise_equal(T const& a, T const& b, Rest... rest) +{ + return pairwise_equal(a, b) && pairwise_equal(rest...); +} + +void do_variadic() +{ + variadic(15, 15); + variadic(12); + assert(pairwise_equal(5, 5, 2.0, 2.0, std::string("a"), std::string("a"))); + assert(! pairwise_equal(5, 5, 2.0, 3.0)); +} + +// deleted, default + +class B +{ + public: + B(int x) : + x(x) + { + } + B() : B(5) + { + } + int getX() const + { + return x; + } + + virtual ~B() = default; + B(B const&) = delete; + B& operator=(B const&) = delete; + + private: + int x; +}; + +void do_default_deleted() +{ + B b1; + assert(5 == b1.getX()); + assert(std::is_copy_constructible::value); + assert(! std::is_copy_constructible::value); +} + +// smart pointers + +class C +{ + public: + C(int id = 0) : + id(id) + { + incr(id); + } + ~C() + { + decr(id); + } + C(C const& rhs) : C(rhs.id) + { + } + C& operator=(C const& rhs) + { + if (&rhs != this) + { + decr(id); + id = rhs.id; + incr(id); + } + return *this; + } + static void check(size_t size, int v, int count) + { + assert(m.size() == size); + auto p = m.find(v); + if (p != m.end()) + { + assert(p->second == count); + } + } + + private: + void incr(int i) + { + ++m[i]; + } + void decr(int i) + { + if (--m[i] == 0) + { + m.erase(i); + } + } + + static std::map m; + int id; +}; + +std::map C::m; + +std::shared_ptr make_c(int id) +{ + return std::make_shared(id); +} + +std::shared_ptr make_c_array(std::vector const& is) +{ + auto p = std::shared_ptr(new C[is.size()], std::default_delete()); + C* pp = p.get(); + for (size_t i = 0; i < is.size(); ++i) + { + pp[i] = C(is.at(i)); + } + return p; +} + +void do_smart_pointers() +{ + auto p1 = make_c(1); + C::check(1, 1, 1); + auto p2 = make_c_array({2, 3, 4, 5}); + for (auto i: {1, 2, 3, 4, 5}) + { + C::check(5, i, 1); + } + { + C::check(5, 1, 1); + C c3(*p1); + C::check(5, 1, 2); + } + C::check(5, 1, 1); + p1 = nullptr; + C::check(4, 1, 0); + p2 = nullptr; + C::check(0, 0, 0); + { + std::unique_ptr p3(new C(6)); + C::check(1, 6, 1); + } + C::check(0, 0, 0); +} + +int main() +{ + do_functional(); + do_inttypes(); + do_iteration(); + do_variadic(); + do_default_deleted(); + do_smart_pointers(); + std::cout << "assertions passed\n"; + return 0; +} diff --git a/libtests/qtest/cxx11.test b/libtests/qtest/cxx11.test new file mode 100644 index 00000000..5efbd87f --- /dev/null +++ b/libtests/qtest/cxx11.test @@ -0,0 +1,16 @@ +#!/usr/bin/env perl +require 5.008; +use warnings; +use strict; + +require TestDriver; + +my $td = new TestDriver('c++-11'); + +$td->runtest("C++-11", + {$td->COMMAND => "cxx11"}, + {$td->STRING => "assertions passed\n", + $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + +$td->report(1); -- cgit v1.2.3-54-g00ecf