├── .gitignore ├── README.md ├── attributes.cc ├── constexpr.cc ├── exchange.cc ├── functors.cc ├── inference.cc ├── initialization.cc ├── iterator.cc ├── lambda.cc ├── literals.cc ├── make_unique.cc ├── quoted.cc ├── range.cc ├── sequence.cc ├── traits.cc ├── tuple.cc └── variable_template.cc /.gitignore: -------------------------------------------------------------------------------- 1 | a.out 2 | *.swp 3 | *.o 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | C++14 Snippets 2 | ============== 3 | 4 | Learn the new C++14 features by examples 5 | 6 | 7 | Description 8 | ----------- 9 | 10 | Source for the references is the free [N3936](https://raw.githubusercontent.com/cplusplus/draft/ab1e49a22e78386e263e787cd1e705f9c81e951f/papers/N3936.pdf) working draft (pdf), dated 2nd March 2014 11 | 12 | clang++3.4 -std=c++1y -stdlib=libc++ -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic xxx.cc 13 | 14 | Note: feel free to help out, search for "TODO" 15 | 16 | 17 | | File | Reference | Description | 18 | | ---------------------------------------------- | --------------------- | --------------------------------------------------------------- | 19 | | [literals.cc](literals.cc) | tbd | string literals, binary literals, digit separator | 20 | | [lambda.cc](lambda.cc) | tbd | generic lambdas, lambda captures | 21 | | [inference.cc](inference.cc) | tbd | return type inference | 22 | | [iterator.cc](iterator.cc) | tbd | cbegin, cend | 23 | | [constexpr.cc](constexpr.cc) | tbd | relaxed constexpr restrictions, const constexpr | 24 | | [make_unique.cc](make_unique.cc) | tbd | make\_unique | 25 | | [tuple.cc](tuple.cc) | tbd | get | 26 | | [attributes.cc](attributes.cc) | tbd | deprecated attribute | 27 | | [quoted.cc](quoted.cc) | tbd | quoted | 28 | | [exchange.cc](exchange.cc) | tbd | exchange | 29 | | [sequence.cc](sequence.cc) | tbd | integer\_sequence | 30 | | [functors.cc](functors.cc) | tbd | type deduction for greater<> et al. | 31 | | [range.cc](range.cc) | tbd | range overloads for equal, mismatch, is\_permutation | 32 | | [variable_template.cc](variable_template.cc) | tbd | templated variables | 33 | | [initialization.cc](initialization.cc) | tbd | aggregate initialization, brace elision | 34 | | [traits.cc](traits.cc) | tbd | aliases for trait's ::type, e.g. is\_same\_t | 35 | 36 | Warning: not a complete list of changes (yet) -- work in progress. 37 | 38 | Here's my [C++11 edition](https://github.com/daniel-j-h/cpp11-snippets). 39 | But keep in mind: the C++11 edition is from two years ago as I was still learning C++11. And it's not really maintained anymore. 40 | -------------------------------------------------------------------------------- /attributes.cc: -------------------------------------------------------------------------------- 1 | // works on functions, classes.. 2 | class [[deprecated("this was not a good idea to begin with")]] 3 | stream { }; 4 | 5 | int main() { 6 | 7 | // ..also on variables; reason is optional 8 | [[deprecated("don't use this anymore")]] 9 | auto make_stream = [](){ return stream{}; }; 10 | 11 | make_stream(); 12 | 13 | // see: http://en.cppreference.com/w/cpp/language/attributes 14 | 15 | } 16 | -------------------------------------------------------------------------------- /constexpr.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | // TODO: relaxed constexpr restrictions, const constexpr 7 | 8 | // see: http://en.cppreference.com/w/cpp/language/constexpr 9 | 10 | } 11 | -------------------------------------------------------------------------------- /exchange.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | // TODO 6 | 7 | // see: http://en.cppreference.com/w/cpp/utility/exchange 8 | 9 | } 10 | -------------------------------------------------------------------------------- /functors.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() { 10 | 11 | std::vector svec{"xxx", "xxxx", "x", "xx"}; 12 | auto second = std::begin(svec) + 1; 13 | 14 | // comparator's operator() parameter type is deduced from its arguments 15 | std::nth_element(std::begin(svec), second, std::end(svec), std::less<>{}); 16 | assert(*second == "xx"); // second smallest element is xx 17 | 18 | // no need to write std::greater{} 19 | std::nth_element(std::begin(svec), second, std::end(svec), std::greater<>{}); 20 | assert(*second == "xxx"); // second largest element is xxx 21 | 22 | 23 | // count_ones([0 1 1 0] | [1 1 0 0]) = count_ones([1 1 1 0]) == 3 24 | std::vector lhs{0, 1, 1, 0}, rhs{1, 1, 1, 0}; 25 | auto count = std::inner_product(std::begin(lhs), std::end(lhs), std::begin(rhs), 26 | 0, std::plus<>{}, std::logical_or<>{}); 27 | // functor<>{} instantiates a new functor template with generic operator() 28 | assert( count == 3 ); 29 | 30 | // see: http://en.cppreference.com/w/cpp/utility/functional#Function_objects 31 | 32 | } 33 | -------------------------------------------------------------------------------- /inference.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // return type deduced by rules of template argument deduction, i.e. you have to write: "const auto&" explicitely as return type 4 | template 5 | auto identity(const T& id) { 6 | return id; 7 | } 8 | 9 | // return type deduced by rules of decltype 10 | template 11 | decltype(auto) identity2(const T& id) { 12 | return id; 13 | } 14 | 15 | int main() { 16 | int r = 2; 17 | 18 | static_assert( std::is_same< decltype(identity(r)), int >(), "template argument deduction did not return int" ); 19 | static_assert( std::is_same< decltype(identity2(r)), int const& >(), "decltype type deduction did not return int const&" ); 20 | 21 | // you'd have to write "const auto&" instead 22 | decltype(auto) rv = identity2(r); 23 | static_assert( std::is_same< decltype(rv), int const& >(), "variable initializer decltype type deduction did not return int const&" ); 24 | 25 | // note: return type deduction even works with recursion, as long as the recursive call is not the first return 26 | 27 | // see: 28 | // - http://en.cppreference.com/w/cpp/language/function#Return_type_deduction 29 | // - http://en.cppreference.com/w/cpp/language/auto 30 | 31 | } 32 | -------------------------------------------------------------------------------- /initialization.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | // without brace elision 7 | std::array r{{2, 3}}; 8 | assert( r.size() == 2 ); 9 | 10 | // now with brace elision 11 | std::array s{2, 3}; 12 | assert( s.size() == 2 ); 13 | 14 | // see: http://en.cppreference.com/w/cpp/language/aggregate_initialization 15 | 16 | } 17 | -------------------------------------------------------------------------------- /iterator.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | 8 | // freestanding cbegin, cend for const-qualified iterators 9 | std::vector ivec{2, 3, 4}; 10 | assert( std::distance(std::cbegin(ivec), std::cend(ivec)) == 3 ); 11 | static_assert( std::is_same< decltype(std::cbegin(ivec)), decltype(ivec)::const_iterator >(), "expected const-qualified iterator" ); 12 | 13 | // rbegin, rend, crbegin, crend -- note: convert reverse iterator to iterator via .base() 14 | assert( std::crbegin(ivec).base() == std::cend(ivec) ); 15 | 16 | // constexpr allows for compile time checks 17 | int iarr[]{2, 3, 4}; 18 | static_assert( std::cend(iarr) - std::cbegin(iarr) == 3, "expected three elements" ); 19 | 20 | // see: 21 | // - http://en.cppreference.com/w/cpp/iterator/begin 22 | // - http://en.cppreference.com/w/cpp/iterator/end 23 | 24 | } 25 | -------------------------------------------------------------------------------- /lambda.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | 10 | // returns a function that takes a pair of generic iterators, joining the elements into a stream 11 | auto joiner = [](auto& stream, auto delim) { 12 | return [=,&stream](auto first, auto last) { 13 | static_assert( std::is_same(), "iterators of unequal type" ); 14 | std::copy(first, last, std::ostream_iterator(stream, delim)); 15 | }; 16 | }; 17 | 18 | 19 | // joins elements to cout separated by whitespace 20 | auto out_joiner = joiner(std::cout, " "); 21 | 22 | // may now be used on any pair of iterators 23 | std::vector cvec{'r', 's', 't'}; 24 | out_joiner(std::cbegin(cvec), std::cend(cvec)); 25 | 26 | std::vector ivec{2, 3, 4}; 27 | out_joiner(std::cbegin(ivec), std::cend(ivec)); 28 | 29 | // note: we need the is_same check, otherwise you could pass: begin(cvec), end(ivec) 30 | 31 | 32 | // TODO: capture expression 33 | 34 | } 35 | -------------------------------------------------------------------------------- /literals.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | 8 | // unfortunately literals have their own namespaces 9 | using namespace std::literals; 10 | 11 | // std::string literal 12 | auto s = "Hello"s; 13 | 14 | assert( s.length() == 5 ); 15 | assert(( std::is_same() )); 16 | 17 | 18 | // or use the inlined namespace 19 | using namespace std::literals::chrono_literals; 20 | 21 | auto sec = 1s; 22 | auto minute = 1min; 23 | auto hour = 1h; 24 | 25 | assert( minute == 60 * sec ); 26 | assert( hour == 60 * minute ); 27 | 28 | 29 | // binary literals 30 | assert(0b1111 == 0xF); 31 | 32 | 33 | // separator ' 34 | assert( 0b1111'1111'1111'1111 == 0xFFFF ); 35 | assert( 10'000'000 == 10 * 1'000'000 ); 36 | 37 | 38 | // see: http://en.cppreference.com/w/cpp/language/user_literal 39 | 40 | } 41 | -------------------------------------------------------------------------------- /make_unique.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | // TODO 6 | 7 | // see: http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique 8 | 9 | } 10 | -------------------------------------------------------------------------------- /quoted.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | // TODO 6 | 7 | // see: http://en.cppreference.com/w/cpp/io/manip/quoted 8 | 9 | } 10 | -------------------------------------------------------------------------------- /range.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | 8 | std::vector r{2, 3, 4}; 9 | std::vector s{2, 3}; 10 | 11 | // overloads no longer assume same length; instead they now take: [first, last), [first2, last2) 12 | auto equal = std::equal(std::begin(r), std::end(r), std::begin(s), std::end(s)); 13 | assert( !equal ); 14 | 15 | auto mismatch = std::mismatch(std::begin(r), std::end(r), std::begin(s), std::end(s)); 16 | assert( mismatch.first == std::end(r) - 1 ); 17 | assert( mismatch.second == std::end(s) ); 18 | 19 | auto permutation = std::is_permutation(std::begin(r), std::end(r), std::begin(s), std::end(s)); 20 | assert( !permutation ); 21 | 22 | // note: consider a range library, e.g. Boost.Range for: equal(r, s); 23 | 24 | // see: 25 | // - http://en.cppreference.com/w/cpp/algorithm/equal 26 | // - http://en.cppreference.com/w/cpp/algorithm/mismatch 27 | // - http://en.cppreference.com/w/cpp/algorithm/is_permutation 28 | 29 | } 30 | -------------------------------------------------------------------------------- /sequence.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | 5 | // TODO 6 | 7 | // see: http://en.cppreference.com/w/cpp/utility/integer_sequence 8 | 9 | } 10 | -------------------------------------------------------------------------------- /traits.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // TODO: 7 | // - more advanced snippets 8 | // - my stdlib does not support x_t instead of x{} or x::type yet, replace if tested 9 | 10 | 11 | // type constraints helper 12 | #define REQUIRES(...) typename=std::enable_if<(__VA_ARGS__)>() 13 | 14 | // concept'ish way of specifying type constraints, such as 15 | template () )> 16 | std::size_t digits(T x) { 17 | return static_cast(::floor(::log10(x)) + 1); 18 | } 19 | 20 | 21 | int main() { 22 | 23 | assert( digits(234) == 3 ); 24 | assert( digits(2) == 1 ); 25 | 26 | // see: http://en.cppreference.com/w/cpp/header/type_traits 27 | 28 | } 29 | -------------------------------------------------------------------------------- /tuple.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | 7 | using namespace std::literals::string_literals; 8 | auto t = std::make_tuple(2, "Hello"s); 9 | 10 | // access by type 11 | assert( std::get(t) == 2 ); 12 | assert( std::get(t) == "Hello"s ); 13 | 14 | // or index as usual 15 | assert( std::get<0>(t) == std::get(t) ); 16 | assert( std::get<1>(t) == std::get(t) ); 17 | 18 | // see: http://en.cppreference.com/w/cpp/utility/tuple/get 19 | 20 | } 21 | -------------------------------------------------------------------------------- /variable_template.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | 6 | // TODO 7 | 8 | // see: http://en.cppreference.com/w/cpp/language/variable_template 9 | 10 | } 11 | --------------------------------------------------------------------------------