#include <iostream>
int main() {
// put "Hello world\n" to the character output
std::cout << "Hello, world!\n";
}
// `int` for integers.
auto meaning_of_life = 42;
// `double` for rational numbers.
auto six_feet_in_metres = 1.8288;
// report if this expression is false
CHECK(six_feet_in_metres < meaning_of_life);
// `string` for text.
auto course_code = std::string("COMP6771");
// `char` for single characters.
auto letter = 'C';
CHECK(course_code.front() == letter);
// `bool` for truth
auto is_cxx = true;
auto is_danish = false;
CHECK(is_cxx != is_danish);
// `int` for integers.
auto const meaning_of_life = 42;
// `double` for rational numbers.
auto const six_feet_in_metres = 1.8288;
// report if this expression is false
CHECK(six_feet_in_metres < meaning_of_life);
auto const x = 10;
auto const y = 173;
auto const sum = 183;
CHECK(x + y == sum);
auto const difference = 163;
CHECK(y - x == difference);
CHECK(x - y == -difference);
auto const product = 1730;
CHECK(x * y == product);
auto const quotient = 17;
CHECK(y / x == quotient);
auto const remainder = 3;
CHECK(y % x == remainder);
auto const x = 15.63;
auto const y = 1.23;
auto const sum = 16.86;
CHECK(x + y == sum);
auto const difference = 14.4;
CHECK(x - y == difference);
CHECK(y - x == -difference);
auto const product = 19.2249;
CHECK(x * y == product);
auto const expected = 12.7073170732;
auto const actual = x / y;
auto const acceptable_delta = 0.0000001;
CHECK(std::abs(expected - actual) < acceptable_delta);
auto const expr = std::string("Hello, expressions!");
auto const cxx = std::string("Hello, C++!");
CHECK(expr != cxx);
CHECK(expr.front() == cxx[0]);
auto const concat = absl::StrCat(expr, " ", cxx);
CHECK(concat == "Hello, expressions! Hello, C++!");
auto expr2 = expr;
// Abort TEST_CASE if expression is false
REQUIRE(expr == expr2);
auto const hello = std::string("Hello!")
auto hello2 = hello;
// Abort TEST_CASE if expression is false
REQUIRE(hello == hello2);
hello2.append("2");
REQUIRE(hello != hello2);
CHECK(hello.back() == '!');
CHECK(hello2.back() == '2');
auto const is_comp6771 = true;
auto const is_about_cxx = true;
auto const is_about_german = false;
CHECK((is_comp6771 and is_about_cxx));
CHECK((is_about_german or is_about_cxx));
CHECK(not is_about_german);
In C++ we are able to convert types implicitly or explicitly. We will cover this later in the course in more detail.
auto const i = 0;
{
auto d = 0.0;
REQUIRE(d == 0.0);
d = i; // Silent conversion from int to double
CHECK(d == 42.0);
CHECK(d != 41);
}
auto const i = 0;
{
// Preferred over implicit, since your intention is clear
auto const d = static_cast<double>(i);
CHECK(d == 42.0);
CHECK(d != 41);
}
auto const i = 42;
{
// information lost, but we're saying we know
auto const b = static_cast<bool>(i);
CHECK(b == true);
CHECK(b == 42); // bad
CHECK(b == static_cast<bool>(42)); // okay
}
C++ has functions just like other languages. We will explore some together
auto is_about_cxx() -> bool {
return true;
}
CHECK(is_about_cxx());
auto square(int const x) -> int {
return x * x;
}
CHECK(square(2) == 4);
auto area(int const width, int const length) -> int {
return width * length;
}
CHECK(area(2, 4) == 8);
std::string rgb(short r = 0, short g = 0, short b = 0);
rgb();// rgb(0, 0, 0);
rgb(100);// Rgb(100, 0, 0);
rgb(100, 200); // Rgb(100, 200, 0)
rgb(100, , 200); // error
What purpose do these two lines serve?
auto square(int const x) -> int {
return x * x;
}
auto square(double const x) -> double {
return x * x;
}
CHECK(square(2) == 4);
CHECK(square(2.0) == 4.0);
CHECK(square(2.0) != 4);
auto g() -> void;
auto f(int) -> void;
auto f(int, int) -> void;
auto f(double, double = 3.14) -> void;
f(5.6); // calls f(double, double)
Errors in function matching are found during compile time
Return types are ignored. Read more about this here.
auto is_even(int const x) -> bool {
return x % 2 == 0;
}
auto collatz_point_conditional(int const x) -> int {
return is_even(x) ? x / 2
: 3 * x + 1;
}
CHECK(collatz_point_conditional(6) == 3);
CHECK(collatz_point_conditional(5) == 16);
https://en.wikipedia.org/wiki/Collatz_conjecture
auto collatz_point_if_statement(int const x) -> int {
if (is_even(x)) {
return x / 2;
}
return 3 * x + 1;
}
CHECK(collatz_point_if_statement(6) == 3);
CHECK(collatz_point_if_statement(5) == 16);
auto is_digit(char const c) -> bool {
switch (c) {
case '0': [[fallthrough]];
case '1': [[fallthrough]];
case '2': [[fallthrough]];
case '3': [[fallthrough]];
case '4': [[fallthrough]];
case '5': [[fallthrough]];
case '6': [[fallthrough]];
case '7': [[fallthrough]];
case '8': [[fallthrough]];
case '9': return true;
default: return false;
}
}
CHECK(is_digit('6'));
CHECK(not is_digit('A'));
auto const single_digits = std::vector<int>{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
};
auto more_single_digits = single_digits;
REQUIRE(single_digits == more_single_digits);
more_single_digits[2] = 0;
CHECK(single_digits != more_single_digits);
more_single_digits.push_back(0);
CHECK(more_single_digits.size() == 11);
auto const single_digits = std::vector<int>{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
};
more_single_digits.push_back(0);
CHECK(ranges::count(more_single_digits, 0) == 2);
more_single_digits.pop_back();
CHECK(ranges::count(more_single_digits, 0) == 1);
CHECK(std::erase(more_single_digits, 0) == 1);
CHECK(ranges::count(more_single_digits, 0) == 0);
CHECK(ranges::distance(more_single_digits) == 8);
#include <vector>
auto i = 1;
auto& j = i;
j = 3;
CHECK(i == 3)
auto i = 1;
auto const& ref = i;
std::cout << ref << '\n';
i++; // This is fine
std::cout << ref << '\n';
ref++; // This is not
auto const j = 1;
auto const& jref = j; // this is allowed
auto& ref = j; // not allowed
#include <iostream>
auto swap(int x, int y) -> void {
auto const tmp = x;
x = y;
y = tmp;
}
auto main() -> int {
auto i = 1;
auto j = 2;
std::cout << i << ' ' << j << '\n'; // prints 1 2
swap(i, j);
std::cout << i << ' ' << j << '\n'; // prints 1 2... not swapped?
}
#include <iostream>
auto swap(int& x, int& y) -> void {
auto const tmp = x;
x = y;
y = tmp;
}
auto main() -> int {
auto i = 1;
auto j = 2;
std::cout << i << ' ' << j << '\n'; // 1 2
swap(i, j);
std::cout << i << ' ' << j << '\n'; // 2 1
}
// C equivalent
#include <stdio.h>
void swap(int* x, int* y) {
auto const tmp = *x;
*x = *y;
*y = tmp;
}
int main() {
int i = 1;
int j = 2;
printf("%d %d\n", i, j);
swap(&i, &j);
printf("%d %d\n", i, j)
}
auto by_value(std::string const sentence) -> char;
// takes ~153.67 ns
by_value(two_kb_string);
auto by_reference(std::string const& sentence) -> char;
// takes ~8.33 ns
by_reference(two_kb_string);
auto by_value(std::vector<std::string> const long_strings) -> char;
// takes ~2'920 ns
by_value(sixteen_two_kb_strings);
// takes ~13 ns
by_reference(sixteen_two_kb_strings);
auto by_reference(std::vector<std::string> const& long_strings) -> char;
auto all_computer_scientists(std::vector<std::string> const& names) -> bool {
auto const famous_mathematician = std::string("Gauss");
auto const famous_physicist = std::string("Newton");
for (auto const& name : names) {
if (name == famous_mathematician or name == famous_physicist) {
return false;
}
}
return true;
}
auto square_vs_cube() -> bool {
// 0 and 1 are special cases, since they're actually equal.
if (square(0) != cube(0) or square(1) != cube(1)) {
return false;
}
for (auto i = 2; i < 100; ++i) {
if (square(i) == cube(i)) {
return false;
}
}
return true;
}
enum class computing_courses {
intro,
data_structures,
engineering_design,
compilers,
cplusplus,
};
auto const computing101 = computing_courses::intro;
auto const computing102 = computing_courses::data_structures;
CHECK(computing101 != computing102);
struct scientist {
std::string family_name;
std::string given_name;
field_of_study primary_field;
std::vector<field_of_study> secondary_fields;
};
auto const famous_physicist = scientist{
.family_name = "Newton",
.given_name = "Isaac",
.primary_field = field_of_study::physics,
.secondary_fields = {field_of_study::mathematics,
field_of_study::astronomy,
field_of_study::theology},
};
auto const famous_mathematician = scientist{
.family_name = "Gauss",
.given_name = "Carl Friedrich",
.primary_field = field_of_study::mathematics,
.secondary_fields = {field_of_study::physics},
};
CHECK(famous_physicist.given_name
!= famous_mathematician.given_name);
CHECK(famous_physicist.family_name
!= famous_mathematician.family_name);
CHECK(famous_physicist.primary_field
!= famous_mathematician.primary_field);
CHECK(famous_physicist.secondary_fields
!= famous_mathematician.secondary_fields);
CHECK(famous_physicist != famous_mathematician);
struct scientist {
std::string family_name;
std::string given_name;
field_of_study primary_field;
std::vector<field_of_study> secondary_fields;
};
auto operator==(scientist const&) const -> bool = default;
auto computer_scientists = std::unordered_set<std::string>{
"Lovelace",
"Babbage",
"Turing",
"Hamilton",
"Church",
"Borg",
};
REQUIRE(ranges::distance(computer_scientists) == 6);
CHECK(computer_scientists.contains("Lovelace"));
CHECK(not computer_scientists.contains("Gauss"));
computer_scientists.insert("Gauss");
CHECK(ranges::distance(computer_scientists) == 7);
CHECK(computer_scientists.contains("Gauss"));
computer_scientists.erase("Gauss");
CHECK(ranges::distance(computer_scientists) == 6);
CHECK(not computer_scientists.contains("Gauss"));
auto ada = computer_scientists.find("Lovelace");
REQUIRE(ada != computer_scientists.end());
CHECK(*ada == "Lovelace");
computer_scientists.clear();
CHECK(computer_scientists.empty());
auto const no_names = absl::flat_hash_set<std::string>{};
REQUIRE(no_names.empty());
CHECK(computer_scientists == no_names);
#include <unordered_set>
auto country_codes = std::unordered_map<std::string, std::string>{
{"AU", "Australia"},
{"NZ", "New Zealand"},
{"CK", "Cook Islands"},
{"ID", "Indonesia"},
{"DK", "Denmark"},
{"CN", "China"},
{"JP", "Japan"},
{"ZM", "Zambia"},
{"YE", "Yemen"},
{"CA", "Canada"},
{"BR", "Brazil"},
{"AQ", "Antarctica"},
};
CHECK(country_codes.contains("AU"));
CHECK(not country_codes.contains("DE")); // Germany not present
country_codes.emplace("DE", "Germany");
CHECK(country_codes.contains("DE"));
auto check_code_mapping(
std::unordered_map<std::string, std::string> const& country_codes,
std::string const& code,
std::string const& name) -> void {
auto const country = country_codes.find(code);
REQUIRE(country != country_codes.end());
auto const [key, value] = *country;
CHECK(code == key);
CHECK(name == value);
}
#include <unordered_map>
void declared_fn(int arg);
class declared_type;
// This class is defined, but not all the methods are.
class defined_type {
int declared_member_fn(double);
int defined_member_fn(int arg) { return arg; }
};
// These are all defined.
int defined_fn() { return 1; }
int i;
int const j = 1;
auto vd = std::vector<double>();
There are 4 types of program errors that we will discuss
auto main() -> int {
a = 5; // Compile-time error: type not specified
}
#include "catch2/catch.hpp"
auto is_cs6771() -> bool;
TEST_CASE("This is all the code")
CHECK(is_cs6771()); // Link-time error: is_cs6771 not defined.
}
[build] ld.lld: error: unable to find library -ltest_main
[build] clang: error: linker command failed with exit code 1 (use -v to see invocation)
Remember how we couldn't demo yesterday? That was due to a linker error because a whole file was missing!
// attempting to open a file...
if (auto file = std::ifstream("hello.txt"); not file) {
throw std::runtime_error("Error: file not found.\n");
}
auto const empty = std::string("");
CHECK(empty[0] == 'C'); // Logic error: bad character access
auto const s = std::string("");
assert(not s.empty());
CHECK(s[0] == 'C'); // Logic error: bad character access