Keywords from D to P

You can check the part 1 and part 3 before or after reading this one

D-E

F-M

N-P


D

  • decltype: Inspects the declared type of an entity or the type and value category of an expression. See: cppreference/decltype
template<typename T>
auto foo(T t) -> decltype(auto) {
    return std::string();
}
int main() {
    auto x = 10.5;
    if (std::is_same_v<decltype(x), double>) {
        std::cout << "Same types";
    }
    auto l = []() -> decltype(auto) {
        return 10;
    };
}
  • default: It can be used in two different contexts. First, as a clausule in a switch statement to be called in the case the value we try to match it’s not supported by any case. And second, to default initialize special member functions. See: cppreference/default
class S {
    public:
        S() = default;
        ~S() = default;

        int x = 5;
};

int main() {
    S* s = new S();
    switch(s->x) {
        case 1:
            std::cout << "1";
            break;
        default:
            std::cout << "10";
    }
}
class S {
    public:
        S() = delete;
};

int main() {
    int* x = new int(10); // Allocates 4 bytes of memory in the heap.
    delete x; // Release those 4 bytes of memory.
    S* s = new S(); // error: use of deleted function 'S::S()'.
}
  • do: Only used in a do-while-loop to always perform the first iteration. See: cppreference/do
do {
    std::cout << "First and only iteration"
} while(false);
double x = 10.0;
std::cout << sizeof(x); // 8
  • dynamic_cast: Safely converts pointers and references to classes up, down, and sideways along the inheritance hierarchy. It is done at runtime and returns nullptr if the action could’t be done. See: cppreference/dynamic_cast
struct Base
{
    Base() {}
    virtual ~Base() {}
};
 
struct Derived : Base
{
    Derived() {}
    virtual void Foo() {
        std::cout << "Derived::Foo()\n";
    }
};
 
int main()
{
    Base* b = new Derived();
    if (Derived* d = dynamic_cast<Derived*>(b); d != nullptr)
    {
        d->Foo();
    }
}

// Output 
Derived::Foo()

E

  • else: Part of the if statement that executes when the if clausule is not satisfied. See: cppreference/else
if (false) {
} else {
    std::cout << "If statement is false";
}

// Output
If statement is false
  • enum: Enumeration of values for a certain type. If used with the class specifier, our enumeration will be scoped and the values enumareted inside could be repeated. We can also specify the type of our enumeration See: cppreference/enum
enum class e : int {A, B, C};
enum class s : char {A = 'A', B = 'B', C = 'C'};

int main() {
    std::cout << (int)e::C << " " << (char)s::A; // 2 A
}
  • explicit: In this case I have a long article explaining this keyword. It basically avoid making implicit conversion between types. See: rrmprogramming/custom-conversions
// helloworld.cpp
export module helloworld;  // module declaration
import <iostream>;         // import declaration
 
export void hello() {      // export declaration
    std::cout << "Hello world!\n";
}

// main.cpp
import helloworld;  // import declaration
 
int main() {
    hello(); // Prints "Hello World!"
}
extern "C" {
    int open(const char *pathname, int flags); // C function declaration
}
 
int main() {
    int fd = open("test.txt", 0); // calls a C function from a C++ program
}
 
// This C++ function can be called from C code
extern "C" void handler(int) {
    std::cout << "Callback invoked\n"; // It can use C++
}

F

bool b = false;
std::cout << b; // Prints "0"
float f = 10.0;
std::cout << sizeof(f); // 4 bytes.
  • for: There are two ways of using for: for-loop and range-base-for-loop. Iterates for a certain condition. See: cppreference/for
for (int i=0; i<3; i++)
    std::cout << "For-loop: " << i << '\n';
std::vector<int> v = {2, 4, 6};

for (int element : v) 
    std::cout << "Range-based: " << element << '\n';

// Output
For-loop: 1
For-loop: 2
For-loop: 3
Range-based: 2
Range-based: 4
Range-based: 6
class A {
    friend class B;                   // B can access A
    friend void change_value(int x);  // Friend function declaration
    void foo() { std::cout << "A::foo()\n"; }
    int valueA = 10;
};

class B {
   public:
    void call_A() {
        A a;
        a.foo(); // Can access A::foo() because A defines B as friend class.
    }
};

void change_value(int x) {
    A a;
    a.valueA = 50; // Can acces A because its a friend function.
    std::cout << "Change A.value = " << a.valueA << "\n";
}

int main() {
    change_value(10);
    B b;
    b.call_A();
}

// Output
Change A.value = 50
A::foo()

G

int main() {
    int x = 0;
    begin:
        std::cout << x << '\n';
        x++;
        if (x == 3)
            goto end;
        else 
            goto begin;
    end:
}

// Output
1
2
3

I

if (true) {
    std::cout << "Condition true";
}
  • inline: Defines that a function is implemente inline an with this identifier the function will be only inserted once per translation unit. If the function is implemented inline without the specifier, the compiler add it automatically. For example. See: cppreference/inline
Code snippet that shows that void foo inside a struct translates into inline void foo after the compiler does its work.
Code generated by the compiler if inline is missing.
struct A {
    inline void foo() {
        std::cout << "Inlined function";
    }
}
  • int: Integer type used for natural numbers with size of 4 bytes. See: cppreference/int
int x = 10;
std::cout << sizeof(x); // 4 bytes.

L

  • long: Integer type used for natural numbers with size of 8 bytes. See: cppreference/long
long x = 10;
long int y = 10.0;
long long z = 10;
std::cout << sizeof(x); // 8 bytes.
std::cout << sizeof(y); // 8 bytes.
std::cout << sizeof(z); // 8 bytes.

M

  • mutable: Permits modification of the class member declared mutable even if the containing object is declared const. Onlye allowed inside member-functions See: cppreference/mutable
struct A {
    mutable const int* x = new int(10);
    mutable int y = 20;
};

int main() {
    A a;
    a.x = new int(50);
    std::cout << "a.x = " << *a.x << '\n'; // "a.x = 50"
    a.y = 200;
    std::cout << "a.y = " << a.y << '\n'; // "a.y = 200"
}

N

  • namespace: Provides an scoped name to avoid duplicate values. All definitions inside a namespace must be anotated with it. See: cppreference/namespace
namespace n1 {
    void foo() {};
}

int main() {
    n1::foo();
    foo(); // error: 'foo' was not declared in this scope; did you mean 'n1::foo'?
}
{
    int y = 10; // Allocated in the stack, freed after the end of the scope.
    int* x = new int(10); // Allocated on the heap, no deallocated after the scope.
} 
// 4 bytes of 'y' freed.
// 4 bytes of 'x' still in use on the heap.

  • noexcept: Mark a function as not capable of throwing exceptions. It also can be used as operator in order to know if a function can throw exceptions. See: cppreference/noexcept
void foo() noexcept { } // The function will not throw
void foo2() noexcept(false) {} // The function may throw
void foo3( void* foo() noexcept) {} // The function takes a pointer to a function that don' throw
void foo4() { } 

int main(){
    std::cout << noexcept(foo()); // True
    std::cout << noexcept(foo2()); // False
    std::cout << noexcept(foo3()); // False
    std::cout << noexcept(foo4()); // False
}
  • not: Performs a logic not operation. It is equivalent to !. See: cppreference/not
bool b1 = false;
bool b2 = not b1;
if (b2 == true) {
    std::cout << b2; // True;
}
  • not_eq: Performs a logic not equal operation. It is equivalent to !=. See: cppreference/not_eq
bool b1 = false;
bool b2 = not b1;
if (b2 not_eq b1) {
    std::cout << "They are not equal";
}
int* x = nullptr;
if ( x == 0 ) {
    std::cout << "x is nullptr";
}

O

struct A {
    void operator()() const {
         std::cout << "A::operator()";
    }
};

int main() {
    A a;
    a(); // Prints: "A::operator()"
    a.operator()(); // Can be called this way aswell
}
  • or: Performs a logic or operation. It is equivalent to ||. See: cppreference/or
if ( true or false ) {
        std::cout << "At least one is true";
}
  • or_eq: Performs a bitwise or operation with the value itself. It is equivalent to |=. See: cppreference/or_eq
auto b1 = 0xb00110000;
auto b2 = 0xb00101111;
 
std::cout << std::hex << b1 << '\n'; // b00110000
b1 or_eq b2;
std::cout << std::hex << b1 << '\n'; // b00111111

P

  • private: Access specifier that mark member functions and variables only visible inside the member. Structures are prublic by default and classes are private. See: cppreference/private
struct A {
    private:
        int x = 10;
};

int main() {
    A a;
    a.x; // error: 'int A::x' is private within this context
}
  • protected: The member functions and variables are only visible inside the class itself and the ones that derive from it. See: cppreference/protected
struct A {
    protected:
        int x = 10;
};

struct B : A {
    void foo() {
        std::cout << x;
    }
};
  • public: Member functions and member variables are visible from outside the member aswell. See: cppreference/public
struct A {
    public:
        int x = 10;
};

int main() {
    A a;
    std::cout << a.x;
}

Check part 3