Skip to content

Cpp guidelines

Pavel I. Kryukov edited this page Feb 28, 2021 · 13 revisions

Type casting

  • For extending integer casts (e.g. from uint32 to uint64) we use T{} syntax: auto x = uint64{y};
  • For narrowing integer casts (e.g. from uint64 to uint32) we use 'narrow_castmacro:x = narrow_cast( y);`
  • Cast between signed/unsigned values is considered narrowing
  • To cast between different representations of const char* argv const*, we use argv_cast overloads
  • For casting pointers from/to std::byte* pointer, we use byte_cast
  • static_cast should be used for enum/int conversions and avoided in other cases
  • reinterpret_cast and const_cast must not be used, except implementing other casts
  • dynamic_cast is allowed once it has no significant performance impact

Passing arguments

We try to return all objects from functions using structures, or, at least pairs and tuples:

int value;
bool flag = foo( argument, &value); // worse

FooResult result = foo( argument); // better
auto result = foo( argument); // even better

std::pair<bool, int> result = foo( argument); // acceptable, but not the best

auto[flag, value] = foo( argument); // might be nice

If an object should be mutated inside a function, we use C raw pointer instead of C++ reference

void process_instruction(Instr* instr); // preferrable
process_instruction(&fetched_instr); // '&' emphasizes object is mutated

void process_instruction(Instr& instr); // avoid
process_instruction(fetched_instr); // is fetched_instr mutated?

this

this keyword must be avoided as much as possible.

Default arguments

Default arguments are not allowed. Use explicit overload and/or different function names:

    // Avoid
    auto process_value(int value = 0);

    // Prefer
    auto process_value(int value);
    auto process_value();

    // Even better
    auto process_value(int value);
    auto process_zero();

Integer types

We do not use predefined C++ types as they have badly defined sizes. Instead, we use <infra/types.h> types:

  • int8, int16, int32, int64
  • uint8, uint16, uint32, uint64
  • Addr — to represent guest machine address and derived types like address masks, BPU targets etc.

For the most of cases you have to use uint32. Smaller types must be used only in two cases:

  • when they are explicitly required — like keeping an array of bytes or performing sign extension.
  • when you have to keep the data really dense — so far there are no such needs.

Namespaces

To avoid namespace pollution and possible interference between libraries (e.g. Boost and STL) constructions like using namespace std are strictly prohibited.

Arrays

We do not use C-style arrays, instead we use std::array and std::vector. The only exception is arguments list: it is passed to main and other entry points as a const char* argv[], and forwarded to POPL or other argument parsing libraries.

Type deduction

We use C++11 type deduction wherever possible:

auto inst = rp_decode_2_memory->read( cycle); // good
FuncInstr inst = rp_decode_2_memory->read( cycle); // worse

Memory management

We do not use 'new'/'delete' and 'malloc/free' Instead, RAII memory management classes should be used, see our manual for smart pointers.

void avoid()
{ 
    auto pointer = new MyClass(arg1, arg2);
    // ...
    delete pointer;
}

void prefer()
{
    auto pointer = std::make_unique<MyClass>(arg1, arg2);
    // ...
}

The exceptions are few low-level memory management classes (PortQueue, LRUCache etc.)

Exceptions and error handling

We distinguish between internal errors and external errors. Internal errors are errors inside simulator like passing -1 way to cache read function. These errors can be handled by C-style assert() and warning() macros; however, we discourage using these macros in favor of comprehensive unit testing.

External errors are errors caused by incorrect user input, like unsupported instruction, invalid cache size setting or ill-formed trace. They must be reported via C++ exceptions. Exception classes must be inherited from Exception class of infra/exception.h.

Clone this wiki locally