C++
Classes | Functions | Variables
test.cxx File Reference
#include "gtest/gtest.h"
#include <algorithm>
#include <any>
#include <deque>
#include <exception>
#include <execution>
#include <filesystem>
#include <future>
#include <iomanip>
#include <iostream>
#include <list>
#include <numeric>
#include <optional>
#include <ranges>
#include <string>
#include <string_view>
#include <thread>
#include <type_traits>
#include <utility>
#include <vector>
Include dependency graph for test.cxx:

Go to the source code of this file.

Classes

class  base
 
class  derived
 
class  base2
 

Functions

std::string_view trim_whitespace (const std::string_view path)
 Remove leading and trailing whitespace. More...
 
 TEST (cpp11, trim_whitespace)
 
std::string remove_control_characters (const std::string_view str)
 Remove non-printable characters. More...
 
 TEST (cpp20, remove_control_characters)
 
constexpr std::string transform_view (const std::string str, const auto func)
 Helper routine to transform a string with a function. More...
 
constexpr char toggle_case (const char c, const bool to_upper)
 Toggle case. More...
 
constexpr char toupper (const char c)
 constexpr version of std::toupper More...
 
constexpr char tolower (const char c)
 constexpr version of std::tolower More...
 
 TEST (cpp11, case_tests_common)
 
constexpr std::string to_lowercase (const std::string str)
 Use the lower case. More...
 
constexpr std::string to_uppercase (const std::string str)
 Use the upper case. More...
 
constexpr std::string to_snakecase (const std::string str)
 Use the Python case. More...
 
 TEST (cpp11, case_tests1)
 
 TEST (cpp11, case_tests2)
 
std::string get_file_name (const std::string_view path)
 You can aslo break down a path using C++17's std::filesystem. More...
 
std::string get_file_extension (const std::string_view path)
 
std::string get_stem (const std::string_view path)
 
 TEST (cpp17, filename_operations)
 
std::vector< std::string > split_string (std::string_view sentence)
 
 TEST (cpp20, split_string)
 
 TEST (cpp20, check_substrings)
 
 TEST (cpp11, range_based_for_loops)
 
 TEST (cpp11, classes_and_type_traits)
 
 TEST (cpp11, auto_type)
 
 TEST (cpp11, lambda_expressions)
 
 TEST (cpp11, exceptions)
 
 TEST (cpp11, brace_initialisers)
 
 TEST (cpp11, narrowing)
 
 TEST (cpp11, learn_the_standard_library)
 
 TEST (cpp11, threading)
 
 TEST (cpp14, return_value_optimisation)
 
 TEST (cpp14, digit_separators)
 
 TEST (cpp17, optional_types)
 
 TEST (cpp17, heterogeneous_types)
 
 TEST (cpp17, filesystem)
 
 TEST (cpp17, parallel_execution_policy)
 
 TEST (cpp17, clamp_values)
 
 TEST (cpp17, compiler_attributes)
 
 TEST (cpp17, maybe_unused_attribute)
 
 TEST (cpp20, ranges_and_views)
 
 TEST (cpp20, reduce_and_accumulate)
 
 TEST (cpp20, deprecated_with_comment)
 
 TEST (cpp20, contains_for_associative_containers)
 

Variables

size_t bird_count = 0
 

Function Documentation

◆ get_file_extension()

std::string get_file_extension ( const std::string_view  path)

Note string_view makes the data immutable, but prefixing const means you also can't reassign path

Definition at line 192 of file test.cxx.

Here is the caller graph for this function:

◆ get_file_name()

std::string get_file_name ( const std::string_view  path)

You can aslo break down a path using C++17's std::filesystem.

Definition at line 186 of file test.cxx.

Here is the caller graph for this function:

◆ get_stem()

std::string get_stem ( const std::string_view  path)

Definition at line 196 of file test.cxx.

Here is the caller graph for this function:

◆ remove_control_characters()

std::string remove_control_characters ( const std::string_view  str)

Remove non-printable characters.

Definition at line 61 of file test.cxx.

Here is the caller graph for this function:

◆ split_string()

std::vector<std::string> split_string ( std::string_view  sentence)

Something that has eluded computer science for decades, and now C++20 has solved it

Definition at line 233 of file test.cxx.

Here is the caller graph for this function:

◆ TEST() [1/30]

TEST ( cpp11  ,
auto_type   
)

Type inference is a game changer. You can simplify complicated (or unknown) type declarations with auto, but it can be a balance of convenience over readability.

Definition at line 418 of file test.cxx.

◆ TEST() [2/30]

TEST ( cpp11  ,
brace_initialisers   
)

There are many more ways to initialise and append to a container.

In C++17 the type of vector can be inferred from the init list.

Definition at line 510 of file test.cxx.

◆ TEST() [3/30]

TEST ( cpp11  ,
case_tests1   
)

Definition at line 162 of file test.cxx.

Here is the call graph for this function:

◆ TEST() [4/30]

TEST ( cpp11  ,
case_tests2   
)

Definition at line 178 of file test.cxx.

Here is the call graph for this function:

◆ TEST() [5/30]

TEST ( cpp11  ,
case_tests_common   
)

Definition at line 119 of file test.cxx.

Here is the call graph for this function:

◆ TEST() [6/30]

TEST ( cpp11  ,
classes_and_type_traits   
)

Not a modern feature, of course, but you should: make everything constant. You ought to be prefixing const as a matter of course and then removing it when you have to: it’s much easier to reason about code when the data are immutable. In an ideal world everything would be constant – like Haskell – but it’s a balance of reason and getting things done.

Knowning that classes sometimes need a virtual destructor always seemed a bit nuanced and error prone. Now you can test it.

Not my rules but a common opinion: structs hold data; but if there's any funtionality, then it should probably be a class.

Definition at line 384 of file test.cxx.

◆ TEST() [7/30]

TEST ( cpp11  ,
exceptions   
)

A key feature of the language but I eschew adding exceptions to my own code; it's much easier to reason about errors where they occur.

Definition at line 500 of file test.cxx.

◆ TEST() [8/30]

TEST ( cpp11  ,
lambda_expressions   
)

Lambda expressions are like function pointers but with a much friendlier implementation. Call them like a regular function or pass them as a parameter; you can also define them in-place so you don't have to go hunting for the implementation.

Definition at line 474 of file test.cxx.

◆ TEST() [9/30]

TEST ( cpp11  ,
learn_the_standard_library   
)

The standard library often expresses intention much more eloquently than a regular for-loop. Note the namespace is omitted for the count_if parameters, see Koenig/argument-dependent lookup (ADL).

Definition at line 574 of file test.cxx.

◆ TEST() [10/30]

TEST ( cpp11  ,
narrowing   
)

Initialising a small type with a large type will generate an error if you use braces. You don't seem to be able to downgrade this a warning.

Definition at line 555 of file test.cxx.

◆ TEST() [11/30]

TEST ( cpp11  ,
range_based_for_loops   
)

I really find it painful to go back to old style for-loops. All those clumsy explicit iterator declarations can be cleaned up beautifully with auto; in fact, we can drop the iterators altogether and avoid that weird i dereferencing idiom. Note you don't have access to the current index (until C++2a), which isn't necessarily a bad thing if you have aspirations of parallelisation.

You can also pass a function object where you would a lambda to std::for_each, and do more complex things like store state between element But this does, of course, make parallelising the operation more complicated.

Definition at line 270 of file test.cxx.

◆ TEST() [12/30]

TEST ( cpp11  ,
threading   
)

Threading gives you the promise of speed at the expense of reasoning, complexity and debugging. But they are much more intuitive now than the old POSIX library.

std::futures are particularly interesting and let you return the stuff you're interested in much more easily: define a routine as a lambda and run it in the background while the main routine gets on with something else; and when we're ready, we block to get the value.

Listen very carefully, I shall say this only once... if you get this reference then you are a senior dev. You can call things only once using statics and lambdas (IIFE); or, use the well-named Standard Library function.

Definition at line 588 of file test.cxx.

◆ TEST() [13/30]

TEST ( cpp11  ,
trim_whitespace   
)

Definition at line 48 of file test.cxx.

Here is the call graph for this function:

◆ TEST() [14/30]

TEST ( cpp14  ,
digit_separators   
)

If you're defining hardware interfaces then you'll probably have register maps defined as hexadecimals; using digit separators can help improve readability in some cases. You can even define things in binary if you like.

Definition at line 653 of file test.cxx.

◆ TEST() [15/30]

TEST ( cpp14  ,
return_value_optimisation   
)

The destructor is called only once despite the nested constructors: see copy elision.

Definition at line 632 of file test.cxx.

◆ TEST() [16/30]

TEST ( cpp17  ,
clamp_values   
)

This would've been really useful in a previous life but I've yet to use of it since! Documented as a reminder.

Definition at line 750 of file test.cxx.

◆ TEST() [17/30]

TEST ( cpp17  ,
compiler_attributes   
)

Tell the compiler you meant to follow through.

Definition at line 767 of file test.cxx.

◆ TEST() [18/30]

TEST ( cpp17  ,
filename_operations   
)

Definition at line 200 of file test.cxx.

Here is the call graph for this function:

◆ TEST() [19/30]

TEST ( cpp17  ,
filesystem   
)

C++17 has a perfectly good interface to the filesystem so you don't need to use something like Qt's QFile.

Definition at line 717 of file test.cxx.

◆ TEST() [20/30]

TEST ( cpp17  ,
heterogeneous_types   
)

std::tuple is like a pair but better, and offers arbitrary collections of heterogeneous types. You can retrieve values by index (which looks a bit odd) or even by type! I think it makes for quite strange code but you can hide much of it with auto.

std::any is a little better thought out.

Definition at line 692 of file test.cxx.

◆ TEST() [21/30]

TEST ( cpp17  ,
maybe_unused_attribute   
)

If a variable is not used in all cases, mark with an attribute. Often happens where things aren't compiled in release.

Definition at line 799 of file test.cxx.

◆ TEST() [22/30]

TEST ( cpp17  ,
optional_types   
)

Optional types overcome the problem of defining a "not initialised" value – say, -1 – which will inevitably used to index an array and cause an explosion. Your functions can now effectively return a "no result".

Definition at line 672 of file test.cxx.

◆ TEST() [23/30]

TEST ( cpp17  ,
parallel_execution_policy   
)

Quite an exciting prospect in C++17 is parallelising existing for-loops simply by adding an execution policy parameter.

Definition at line 732 of file test.cxx.

◆ TEST() [24/30]

TEST ( cpp20  ,
check_substrings   
)

Definition at line 255 of file test.cxx.

◆ TEST() [25/30]

TEST ( cpp20  ,
contains_for_associative_containers   
)

Check a key exists without find or count. Feels much more natural than checking the end stop.

Definition at line 871 of file test.cxx.

◆ TEST() [26/30]

TEST ( cpp20  ,
deprecated_with_comment   
)

Mark things as deprecated before you remove them.

Definition at line 845 of file test.cxx.

◆ TEST() [27/30]

TEST ( cpp20  ,
ranges_and_views   
)

An opportunity to simplify all the begin/end code that's been written since C++11.

Definition at line 814 of file test.cxx.

◆ TEST() [28/30]

TEST ( cpp20  ,
reduce_and_accumulate   
)

There's no need to specify a starting value with reduce, but there are some important considerations.

https://blog.tartanllama.xyz/accumulate-vs-reduce/

Definition at line 828 of file test.cxx.

◆ TEST() [29/30]

TEST ( cpp20  ,
remove_control_characters   
)

Definition at line 71 of file test.cxx.

Here is the call graph for this function:

◆ TEST() [30/30]

TEST ( cpp20  ,
split_string   
)

Definition at line 245 of file test.cxx.

Here is the call graph for this function:

◆ to_lowercase()

constexpr std::string to_lowercase ( const std::string  str)
constexpr

Use the lower case.

Definition at line 147 of file test.cxx.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ to_snakecase()

constexpr std::string to_snakecase ( const std::string  str)
constexpr

Use the Python case.

Definition at line 157 of file test.cxx.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ to_uppercase()

constexpr std::string to_uppercase ( const std::string  str)
constexpr

Use the upper case.

Definition at line 152 of file test.cxx.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ toggle_case()

constexpr char toggle_case ( const char  c,
const bool  to_upper 
)
constexpr

Toggle case.

Definition at line 90 of file test.cxx.

Here is the caller graph for this function:

◆ tolower()

constexpr char tolower ( const char  c)
constexpr

constexpr version of std::tolower

Definition at line 115 of file test.cxx.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ toupper()

constexpr char toupper ( const char  c)
constexpr

constexpr version of std::toupper

Definition at line 110 of file test.cxx.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transform_view()

constexpr std::string transform_view ( const std::string  str,
const auto  func 
)
constexpr

Helper routine to transform a string with a function.

Definition at line 84 of file test.cxx.

Here is the caller graph for this function:

◆ trim_whitespace()

std::string_view trim_whitespace ( const std::string_view  path)

Remove leading and trailing whitespace.

Common string manipulations so you don't get tempted to use a third-party library.

  • trim_whitespace
  • remove_control_characters
  • to_lowercase
  • to_uppercase
  • to_snakecase
  • get_file_name
  • get_file_extension
  • get_stem (the file name without the extension)
  • starts_with
  • ends_with
  • split_string
  • contains

Definition at line 41 of file test.cxx.

Here is the caller graph for this function:

Variable Documentation

◆ bird_count

size_t bird_count = 0

Definition at line 631 of file test.cxx.