Functions

Functions

and exceptions

return_type functionName(/* params */)
try {
  // body
}
catch (exception_type1&) {
  // handler
}
catch (exception_type1&) {
  // handler
}
return_type functionName(/* params */) noexcept {
  // body
}
 
 

Functions

inline

inline return_type functionName(/* params */) {}
inline type variableName /* = initializer */;
 

and variables

// use1.cpp
#include "common.h"
...
// common.h
void noop() {}
int answer = 44;
// use2.cpp
#include "common.h"
...

Multiple definition error

Functions

inline

inline return_type functionName(/* params */) {}
inline type variableName /* = initializer */;
 

and variables

// use1.cpp
#include "common.h"
...
// common.h
void noop();
extern int answer;
// use2.cpp
#include "common.h"
...

Declaration & definition separation

// common.cpp
void noop() {}
int answer = 44;

Functions

inline

inline return_type functionName(/* params */) {}
inline type variableName /* = initializer */;
 

and variables

// use1.cpp
#include "common.h"
...
// common.h
inline void noop();
inline int answer;
// use2.cpp
#include "common.h"
...

Inline

Function

overloading

struct square {
  float side;
}
struct triangle {
  float base, height;
}
struct circle {
  float radius;
}
float areaSquare(const square& s) {
  return s.side * s.side;
}

float areaTriangle(const triangle& tri) {
  return (tri.base * tri.height) / 2.0;
}

float areaCircle(const circle& c) {
  return PI * c.radius * c.radius;
}

Function

overloading

struct square {
  float side;
}
struct triangle {
  float base, height;
}
struct circle {
  float radius;
}
float area(const square& s) {
  return s.side * s.side;
}

float area(const triangle& tri) {
  return (tri.base * tri.height) / 2.0;
}

float area(const circle& c) {
  return PI * c.radius * c.radius;
}
square s = ...;
triangle tri = ...;
circle c = ...;

float a1 = area(s);
float a2 = area(tri);
float a3 = area(c);

Function

overloading

int    add(   int a,    int b) { return a + b; }
short  add( short a,  short b) { return a + b; }
float  add( float a,  float b) { return a + b; }
char   add(  char a,   char b) { return a + b; }

(Templates)

float area(    const square& s) { return s.side * s.side;               }
float area(const triangle& tri) { return (tri.base * tri.height) / 2.0; }
float area(    const circle& c) { return PI * c.radius * c.radius;      }

(Methods, Polymorphism)

file openConnection(
  const std::string& address) {
    openConnection(address, ConnectionFlagsBit::None);
  };
file openConnection(
  const std::string& address,
  ConnectionFlagsBit flags) {
    openConnection(address, flags, std::chrono::milliseconds::zero())
  }
file openConnection(
  const std::string& address,
  ConnectionFlagsBit flags,
  const std::chrono::milliseconds& timeout);

(Default arguments)

add(2.0)
ambiguous

Function

default

file openConnection(
  const std::string& address) {
    openConnection(address, ConnectionFlagsBit::None);
  };
file openConnection(
  const std::string& address,
  ConnectionFlagsBit flags) {
    openConnection(address, flags, std::chrono::milliseconds::zero())
  }
file openConnection(
  const std::string& address,
  ConnectionFlagsBit flags,
  const std::chrono::milliseconds& timeout);

arguments

file openConnection(
  const std::string& address,
  ConnectionFlagsBit flags = ConnectionFlagsBit::None,
  const std::chrono::milliseconds& timeout = std::chrono::milliseconds::zero());
auto

structured binding

variable type deduction

return type deduction

generic lamdas

abbreviated function templates

functions with trailing return type

decltype(auto)

non type template parameter with deduced type

auto

return type

const int x = 0;

auto f() {
    return x;
}

decltype(auto) g() {
    return static_cast<const int&>(x);
}

void use() {
    auto n = f(); // int
    decltype(auto) nd = f(); // int

    auto m = g(); // int
    decltype(auto) md = g(); // const int&
}

return type

trailing

auto functionName(/* params */) -> return_type {
  // body
}
return_type functionName(/* params */) {
  // body
}

compile-time

RUN-TIME

  • performance
  • compile time values
  • instead of code generation / additional build steps

computation

constexpr

template Metaprogramming

Preprocessor

compile-time computation

computation

#ifndef HEADER_GUARD
#define HEADER_GUARD

#include <type_traits>
#include "myheader.h"

#define PI 3.1415926
#define ERROR_MSG "Exception access violation"

#define ADD(ARG1, ARG2) ((ARG1) + (ARG2))

#define STRINGIFY(ARG1) #ARG1
#define CONCAT(ARG1, ARG2) ARG1 ## ARG2
#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)

#ifdef __APPLE__
  #include "apple_specific.h"
#elif __linux__
  #include "linux_specific.h"
#elif _WIN32
  #include "windows_specific.h"
#else
  #error Unsupported platform
#endif

#line 42

#endif // HEADER_GUARD
  • Header guards
  • Includes
  • Constants
  • Compile-time computation
  • Source code transformation
  • Cross-platform compatibility
    • Platform detection
    • Conditional compilation
    • Reporting compilation errors
  • Code generation support

Preprocessor

constexpr

template Metaprogramming

compile-time computation

constexpr

template Metaprogramming

Preprocessor

compile-time computation

constexpr

Variables

constexpr int TATTUQOLTUAE = 42;
constexpr double PI = 3.141592653;

constexpr auto message = "Hello World!";
constexpr auto numbers = { 1, 2, 3, 4, 5 }; // std::initializer_list<int>

constexpr auto [x, y] = func_returning_pair(); // ERROR

Functions

constepxr int ArraySize = 100;
constexpr std::array<int, ArraySize> fib_ar(int n) {
    std::array<int, ArraySize> res{};
    for (int i = 1; i < ArraySize; ++i) {
       res[i] = res[i - 1] + res[i - 2];
    }
    return res;
}
constexpr int ArraySize = 100;
constexpr std::array<int, ArraySize> fib_ar(int n) {
    std::array<int, ArraySize> res{};
    for (int i = 1; i < ArraySize; ++i) {
       res[i] = res[i - 1] + res[i - 2];
    }
    return res;
}
if constexpr (constantExpr)

If

 

constexpr

consteval

constinit

constexpr

uses

type arrayName[constantExpr];
std::array<type, constantExpr> arrayName;
switch (value) {
  case constantExpr:
    //...   
}
if constexpr (constantExpr) {
  //...
}

arrays

templates

switch cases

compile-time computation

Functions

lambda

std::vector<int> v{2, 3, 4, 2, 5, 2, 1};
std::sort(v.begin(), v.end());
std::sort(v.begin(), v.end(), pred_gt);
std::sort(v.begin(), v.end(), pred_mod);
{1, 2, 2, 2, 3, 4, 5}
{5, 4, 3, 2, 2, 2, 1}
{3, 1, 4, 2, 2, 2, 5}
bool pred_gt(int x, int y) {
  return x > y;
}
bool pred_mod(int x, int y) {
  return (x % 3) < (y % 3);
}

Functions

lambda

    bool pred_mod(int x, int y) {
      return (x % 3) < (y % 3);
    }

void foo() {
  std::vector<int> v{2, 3, 4, 2, 5, 2, 1};
  std::sort(v.begin(), v.end(), pred_mod);
}
bool pred_mod(int x, int y) {
  return (x % 3) < (y % 3);
}

Functions

lambda

void foo() {
  std::vector<int> v{2, 3, 4, 2, 5, 2, 1};
  std::sort(v.begin(), v.end(), 
    [](int x, int y) {
      return (x % 3) < (y % 3);
    }
  );
}
bool pred_mod(int x, int y) {
  return (x % 3) < (y % 3);
}

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }
[]{}
[]{ return 25; }

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }
[](int x, int y){ return x + y; }
[](int x){
  if (x % 2 == 0)
    return "EVEN";
  elsereturn "ODD";
}

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }
[](int x, int y) -> int { return x + y; }
[](int x) -> const char* {
  if (x % 2 == 0)
    return "EVEN";
  elsereturn "ODD";
}

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }
[](int x, int y) noexcept -> int { return x + y; }
[](int x) noexcept -> const char* {
  if (x % 2 == 0)
    return "EVEN";
  elsereturn "ODD";
}

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }
void foo(int r) {
  [](){
    r = ...; //error
  }();
}
void foo(int r) {
  [r](){
    r = ...; //ok
  }();
}
[x, y, &z, &w /*...*/]
[x = foo(name)]
[&]
[=]

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }
[m](int x, int y) noexcept -> int { return (x + y) % m; }
[&x]() noexcept -> const char* {
  if (x % 2 == 0)
    return "EVEN";
  elsereturn "ODD";
}

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }
[m](int x, int y) noexcept -> void { m = x + y; }
[m](int x, int y) mutable noexcept -> void { m = x + y; }
int ar[ [](int x, int y) noexcept -> int { return x + y; }(2, 3) ]
int ar[ [](int x, int y) constexpr noexcept -> int { return x + y; }(2, 3) ]

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }
[]() [[noreturn]] { std::abort(); }
[]() [[nodiscard]] { return 12; }
[]() [[deprecated]] { printf("12"); }

Functions

lambda

[captures]<tparams>(params) specifiers noexcept attrs -> ret { body }

Functions

as variables

return_t func(param1_t, param2_t);

return_t (*ptr_name)(param1_t, param2_t) = &func;
void(*lambda1)() = [](){};
void(*lambda2)() = [x](){}; // error

auto ptr_name = &func;
auto lambda1 = [](){};
auto lambda2 = [x](){};

#include <functional>
std::function<return_t(param1_t, param2_t)> func_2 = func;
std::function<void()> lambda1 = [](){};
std::function<void()> lambda2 = [x](){};

Functions

Made with Slides.com