C++ Core Guidelines
and the Guideline Support Library
Thomas Pollak
1972:
C
1983:
Renamed
to C++
What is it good for?
 C++ is very flexible and unfortunately also quite complicated
 Basically let’s us do everything, even if it is dangerous
 You can find a lot of “advices” on the web, which are just bad
 Bjarne Stroustrup: “Within C++ is a smaller, simpler, safer language struggling to get out”
1979:
C with
Classes
1998:
New ISO
Standard
C++98
2003:
New ISO
Standard
C++03
2011:
New ISO
Standard
C++11
(inf. C++0x)
2014:
New ISO
Standard
C++14
2017:
New ISO
Standard
C++17
Bjarne StroustrupKen Thompson (left)
Dennis Ritchie (right)
1972:
C
1983:
Renamed
to C++
1979:
C with
Classes
1998:
New ISO
Standard
C++98
2003:
New ISO
Standard
C++03
2011:
New ISO
Standard
C++11
(inf. C++0x)
2014:
New ISO
Standard
C++14
2017:
New ISO
Standard
C++17
What is it good for?
Use a subset of safe, modern C++ features and apply rules to avoid crashes,
undefined behaviour and similar.
Core Guidelines
How can I use them?
 https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md
 Work in progress, sometimes controversial + you can also contribute!
 The document gives advices how to write good C++ code
 Supports you with a library, the Guideline Support Library (GSL)
 Tools that can check these rules
 VisualStudio with an additional Nuget package (via the Analyze function)
 Clang-tidy (via command line)
 Let’s take a look at some samples (not complete, nor ordered by importance)
Samples: P.1 Express ideas directly in code
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#p1-express-ideas-directly-in-code
class Date {
public:
Month month() const; // do
int month(); // don't
// ...
};
//don't
void f(vector<string>& v, string val)
{
int index = -1;
for (int i = 0; i < v.size(); ++i)
if (v[i] == val) {
index = i;
break;
}
// ...
}
//do
void f(vector<string>& v, string val)
{
auto p = find(begin(v), end(v), val);
// ...
}
Samples: P.5 Prefer compile-time checking to
run-time checking
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#p5-prefer-compile-time-checking-to-run-time-checking
//don’t
void read(int* p, int n); // read max n integers into *p
//do
void read(span<int> r); // read into the range of integers r
//the span<T> template is supplied via the GSL
Samples: I.4 Make interfaces precisely and
strongly typed
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i4-make-interfaces-precisely-and-strongly-typed
void pass(void* data); // void* is suspicious, always
//don’t
void draw_rect(int, int, int, int); // great opportunities for mistakes
draw_rect(p.x, p.y, 10, 20); // what does 10, 20 mean?
//do
void draw_rectangle(Point top_left, Point bottom_right);
void draw_rectangle(Point top_left, Size height_width);
draw_rectangle(p, Point{10, 20}); // two corners
draw_rectangle(p, Size{10, 20}); // one corner and a (height, width) pair
Samples: I.6 Prefer Expects() for expressing preconditions
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i6-prefer-expects-for-expressing-preconditions
int area(int height, int width)
{
Expects(height > 0 && width > 0); // good
if (height <= 0 || width <= 0) my_error(); // obscure
// ...
}
//Preconditions can be stated in many ways, including comments, if-
//statements, and assert(). This can make them hard to distinguish from
//ordinary code, hard to update, hard to manipulate by tools, and may //have
the wrong semantics (do you always want to abort in debug mode //and check
nothing in productions runs?).
//Preconditions should be part of the interface rather than part of the
//implementation, but we don't yet have the language facilities to do
//that.
//The Expects(cond) macro is supplied via the GSL
Samples: I.9 If an interface is a template, document its
parameters using concepts
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i9-if-an-interface-is-a-template-document-its-parameters-using-concepts
template<typename Iter, typename Val>
// requires InputIterator<Iter> && EqualityComparable<ValueType<Iter>>, Val>
Iter find(Iter first, Iter last, Val v)
{
// ...
}
//Note:
//Soon most compilers might be able to check requires clauses and you can
//simply remove once the comment double slashes //.
Samples: I.11 Never transfer ownership by a raw pointer
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i11-never-transfer-ownership-by-a-raw-pointer-t
// don't
X* compute(args)
{
X* res = new X{};
// ...
return res;
}
//do
vector<double> compute(args)
{
vector<double> res(10000);
// ...
return res;
}
Samples: I.12 Declare a pointer that must not be null
as not_null
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i12-declare-a-pointer-that-must-not-be-null-as-not_null
int length(const char* p); // is length(nullptr) valid?
length(nullptr); // OK?
int length(not_null<const char*> p);// better: p cannot be nullptr
int length(const char* p); // we must assume that p can be nullptr
//the not_null<T> template is supplied via the GSL
Samples: F.3 Keep functions short and simple
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f3-keep-functions-short-and-simple
//There is a lot of discussion how many lines of code are a “good” size for
//function/method. Usually if it does not fit on the screen any more you
//should start to think how to make it simpler.
//Without naming a reference I hope that we can agree that anything beyond
//250 lines is maybe too long. People also argue that loc is not a good
//way of measuring code complexity (however it is easy to check).
Samples: F.51 Where there is a choice, prefer default
arguments over overloading
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f51-where-there-is-a-choice-prefer-default-arguments-over-overloading
//so this is better
void print(const string& s, format f = {});
//than
void print(const string& s); // use default format
void print(const string& s, format f);
//There is no guarantee that a set of overloaded functions all implement the same semantics.
//The use of default arguments can avoid code replication.
Samples: C.20 If you can avoid defining default
operations, do
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c20-if-you-can-avoid-defining-default-operations-do
struct Named_map {
public:
// ... no default operations declared ...
private:
string name;
map<int, int> rep;
};
Named_map nm; // default construct
Named_map nm2 {nm}; // copy construct
//defining no constructor is also known as “rule of zero”
Samples: C.45 Don't define a default constructor that only
initializes data members; use in-class member initializers instead
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c45-dont-define-a-default-constructor-that-only-initializes-data-members-
use-in-class-member-initializers-instead
class X1 { // BAD: doesn't use member initializers
string s;
int i;
public:
X1() :s{"default"}, i{1} { }
// ...
};
class X2 {
string s = "default";
int i = 1;
public:
// use compiler-generated default constructor
// ...
};
Samples: C.131 Avoid trivial getters and setters
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c131-avoid-trivial-getters-and-setters
class point {
int x;
int y;
public:
point(int xx, int yy) : x{xx}, y{yy} { }
int get_x() { return x; }
void set_x(int xx) { x = xx; }
int get_y() { return y; }
void set_y(int yy) { y = yy; }
// no behavioral member functions
};
//basically the same like this:
struct point {
int x = 0;
int y = 0;
};
Samples: C.140 Do not provide different default
arguments for a virtual function and an overrider
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c140-do-not-provide-different-default-arguments-for-a-virtual-function-and-an-overrider
class base {
public:
virtual int multiply(int value, int factor = 2) = 0;
};
class derived : public base {
public:
int multiply(int value, int factor = 10) override;
};
derived dr;
base& bs = dr;
bs.multiply(10); // these two calls will call the same function but
dr.multiply(10); // with different arguments and so different results
Samples: Enum.1 Prefer enums over macros
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#enum-enumerations
//don’t
//Webcolors in header x
#define RED 0xFF0000
#define GREEN 0x00FF00
#define BLUE 0x0000FF
//also bad
//Productinfo in header y
#define RED 0
#define PURPLE 1
#define BLUE 2
int webby = BLUE; // wrong header could now mean “webby == 2”
//do
enum class Webcolor { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF };
enum class Productinfo { red = 0, purple = 1, blue = 2 };
int webby = blue; // error: be specific (this is a class enum, not a plain enum)
Webcolor webby = Webcolor::blue;
Samples: ES.5 Keep scopes small
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es5-keep-scopes-small
void use()
{
int i;
// bad: i is needlessly accessible after loop
for (i = 0; i < 20; ++i) { /* ... */ }
// no intended use of i here
// good: i is local to for-loop
for (int i = 0; i < 20; ++i) { /* ... */ }
// good: pc is local to if-statement
if (auto pc = dynamic_cast<Circle*>(ps)) {
// ... deal with Circle ...
}
else {
// ... handle error ...
}
}
Samples: ES.20 Always initialize an object
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es20-always-initialize-an-object
void use(int arg)
{
int i; // bad: uninitialized variable
// ...
i = 7; // initialize i
}
//No, i = 7 does not initialize i; it assigns to it.
//Also, i can be read in the ... part. Better:
void use(int arg)
{
int i = 7; // OK: initialized
string s; // OK: default initialized
// ...
}
Samples: ES.50 Don't cast away const
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es50-dont-cast-away-const
void bad_function(const MyClass* cInstance) {
...
if(cInstance.max_bytes>MAX_VAL) {
//bad sample
MyClass* instance = const_cast<Myclass*>(cInstance);
++instance.max_bytes;
}
}
//if really needed MyClass can be change, eg:
class MyCLass {
public:
mutable std::int32_t max_bytes; //only a subset can be changed,
//not the whole class
...
}
Samples: P.8 Don't leak any resources
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#p8-dont-leak-any-resources
void f(const char* name)
{
FILE* input = fopen(name, "r");
// ...
if (something) return; // bad: A file handle might leak
// ...
fclose(input);
}
//Prefer RAII:
void f(const char* name)
{
ifstream input {name};
// ...
if (something) return; // OK: no leak
// ...
}
Samples: R.5 Don't heap-allocate unnecessarily
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r5-dont-heap-allocate-unnecessarily
void f(int n)
{
auto p = new Gadget{n};
// ...
delete p;
}
//Instead, use a local variable:
void f(int n)
{
Gadget g{n};
// ...
}
Samples: R.11 Avoid calling new and delete explicitly
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r11-avoid-calling-new-and-delete-explicitly
auto myObject = new MyObject{“MyObj”}; //bad
auto myObjectUnique = std::make_unique<MyObject>(“MyObj”); //better
//in case you need to share the resource in your application:
auto myObjectShared = std::make_shared<MyObject>(“MyObj”);
//most libraries come with some kind of smart pointers
//doing more or less the same (if you cannot use STL)
Samples: T.1 Use templates to raise the level o
abstraction of code
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#t1-use-templates-to-raise-the-level-of-abstraction-of-code
template<typename T, typename A>
// requires Arithmetic<T>
A sum(vector<T>& v, A s)
{
for (auto x : v) s += x;
return s;
}
//For additional generality and reusability, we could also use a
//more general Container or Range concept instead of committing to
//only one container, vector.
How can I use the GSL?
 The GSL has a public specification that can be implemented by anyone
 Currently we can use the Microsoft implementation https://github.com/Microsoft/GSL
 There are other versions too (eg. for C++11), however not updated very frequently
Tools to enforce the rules
 A) CppCoreCheck can be installed as package to any C++ project via the following
command in the VS package manager console (an then run “Analyze”):
 B) Install latest clang from http://llvm.org/releases/download.html and use clang-tidy:
(Unfortunately problematic with Windows headers)
 Both tools check more than only the C++ Core Guidelines – it’s a good idea in general
to use a static code analyzer to avoid errors.
PM> Install-Package Microsoft.CppCoreCheck
$ clang-tidy SOURCE --checks=all -extra-arg=-std=c++14 –extra-arg=-fexceptions

C++ Core Guidelines

  • 1.
    C++ Core Guidelines andthe Guideline Support Library Thomas Pollak
  • 2.
    1972: C 1983: Renamed to C++ What isit good for?  C++ is very flexible and unfortunately also quite complicated  Basically let’s us do everything, even if it is dangerous  You can find a lot of “advices” on the web, which are just bad  Bjarne Stroustrup: “Within C++ is a smaller, simpler, safer language struggling to get out” 1979: C with Classes 1998: New ISO Standard C++98 2003: New ISO Standard C++03 2011: New ISO Standard C++11 (inf. C++0x) 2014: New ISO Standard C++14 2017: New ISO Standard C++17 Bjarne StroustrupKen Thompson (left) Dennis Ritchie (right)
  • 3.
    1972: C 1983: Renamed to C++ 1979: C with Classes 1998: NewISO Standard C++98 2003: New ISO Standard C++03 2011: New ISO Standard C++11 (inf. C++0x) 2014: New ISO Standard C++14 2017: New ISO Standard C++17 What is it good for? Use a subset of safe, modern C++ features and apply rules to avoid crashes, undefined behaviour and similar. Core Guidelines
  • 4.
    How can Iuse them?  https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md  Work in progress, sometimes controversial + you can also contribute!  The document gives advices how to write good C++ code  Supports you with a library, the Guideline Support Library (GSL)  Tools that can check these rules  VisualStudio with an additional Nuget package (via the Analyze function)  Clang-tidy (via command line)  Let’s take a look at some samples (not complete, nor ordered by importance)
  • 5.
    Samples: P.1 Expressideas directly in code https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#p1-express-ideas-directly-in-code class Date { public: Month month() const; // do int month(); // don't // ... }; //don't void f(vector<string>& v, string val) { int index = -1; for (int i = 0; i < v.size(); ++i) if (v[i] == val) { index = i; break; } // ... } //do void f(vector<string>& v, string val) { auto p = find(begin(v), end(v), val); // ... }
  • 6.
    Samples: P.5 Prefercompile-time checking to run-time checking https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#p5-prefer-compile-time-checking-to-run-time-checking //don’t void read(int* p, int n); // read max n integers into *p //do void read(span<int> r); // read into the range of integers r //the span<T> template is supplied via the GSL
  • 7.
    Samples: I.4 Makeinterfaces precisely and strongly typed https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i4-make-interfaces-precisely-and-strongly-typed void pass(void* data); // void* is suspicious, always //don’t void draw_rect(int, int, int, int); // great opportunities for mistakes draw_rect(p.x, p.y, 10, 20); // what does 10, 20 mean? //do void draw_rectangle(Point top_left, Point bottom_right); void draw_rectangle(Point top_left, Size height_width); draw_rectangle(p, Point{10, 20}); // two corners draw_rectangle(p, Size{10, 20}); // one corner and a (height, width) pair
  • 8.
    Samples: I.6 PreferExpects() for expressing preconditions https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i6-prefer-expects-for-expressing-preconditions int area(int height, int width) { Expects(height > 0 && width > 0); // good if (height <= 0 || width <= 0) my_error(); // obscure // ... } //Preconditions can be stated in many ways, including comments, if- //statements, and assert(). This can make them hard to distinguish from //ordinary code, hard to update, hard to manipulate by tools, and may //have the wrong semantics (do you always want to abort in debug mode //and check nothing in productions runs?). //Preconditions should be part of the interface rather than part of the //implementation, but we don't yet have the language facilities to do //that. //The Expects(cond) macro is supplied via the GSL
  • 9.
    Samples: I.9 Ifan interface is a template, document its parameters using concepts https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i9-if-an-interface-is-a-template-document-its-parameters-using-concepts template<typename Iter, typename Val> // requires InputIterator<Iter> && EqualityComparable<ValueType<Iter>>, Val> Iter find(Iter first, Iter last, Val v) { // ... } //Note: //Soon most compilers might be able to check requires clauses and you can //simply remove once the comment double slashes //.
  • 10.
    Samples: I.11 Nevertransfer ownership by a raw pointer https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i11-never-transfer-ownership-by-a-raw-pointer-t // don't X* compute(args) { X* res = new X{}; // ... return res; } //do vector<double> compute(args) { vector<double> res(10000); // ... return res; }
  • 11.
    Samples: I.12 Declarea pointer that must not be null as not_null https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i12-declare-a-pointer-that-must-not-be-null-as-not_null int length(const char* p); // is length(nullptr) valid? length(nullptr); // OK? int length(not_null<const char*> p);// better: p cannot be nullptr int length(const char* p); // we must assume that p can be nullptr //the not_null<T> template is supplied via the GSL
  • 12.
    Samples: F.3 Keepfunctions short and simple https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f3-keep-functions-short-and-simple //There is a lot of discussion how many lines of code are a “good” size for //function/method. Usually if it does not fit on the screen any more you //should start to think how to make it simpler. //Without naming a reference I hope that we can agree that anything beyond //250 lines is maybe too long. People also argue that loc is not a good //way of measuring code complexity (however it is easy to check).
  • 13.
    Samples: F.51 Wherethere is a choice, prefer default arguments over overloading https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#f51-where-there-is-a-choice-prefer-default-arguments-over-overloading //so this is better void print(const string& s, format f = {}); //than void print(const string& s); // use default format void print(const string& s, format f); //There is no guarantee that a set of overloaded functions all implement the same semantics. //The use of default arguments can avoid code replication.
  • 14.
    Samples: C.20 Ifyou can avoid defining default operations, do https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c20-if-you-can-avoid-defining-default-operations-do struct Named_map { public: // ... no default operations declared ... private: string name; map<int, int> rep; }; Named_map nm; // default construct Named_map nm2 {nm}; // copy construct //defining no constructor is also known as “rule of zero”
  • 15.
    Samples: C.45 Don'tdefine a default constructor that only initializes data members; use in-class member initializers instead https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c45-dont-define-a-default-constructor-that-only-initializes-data-members- use-in-class-member-initializers-instead class X1 { // BAD: doesn't use member initializers string s; int i; public: X1() :s{"default"}, i{1} { } // ... }; class X2 { string s = "default"; int i = 1; public: // use compiler-generated default constructor // ... };
  • 16.
    Samples: C.131 Avoidtrivial getters and setters https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c131-avoid-trivial-getters-and-setters class point { int x; int y; public: point(int xx, int yy) : x{xx}, y{yy} { } int get_x() { return x; } void set_x(int xx) { x = xx; } int get_y() { return y; } void set_y(int yy) { y = yy; } // no behavioral member functions }; //basically the same like this: struct point { int x = 0; int y = 0; };
  • 17.
    Samples: C.140 Donot provide different default arguments for a virtual function and an overrider https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c140-do-not-provide-different-default-arguments-for-a-virtual-function-and-an-overrider class base { public: virtual int multiply(int value, int factor = 2) = 0; }; class derived : public base { public: int multiply(int value, int factor = 10) override; }; derived dr; base& bs = dr; bs.multiply(10); // these two calls will call the same function but dr.multiply(10); // with different arguments and so different results
  • 18.
    Samples: Enum.1 Preferenums over macros https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#enum-enumerations //don’t //Webcolors in header x #define RED 0xFF0000 #define GREEN 0x00FF00 #define BLUE 0x0000FF //also bad //Productinfo in header y #define RED 0 #define PURPLE 1 #define BLUE 2 int webby = BLUE; // wrong header could now mean “webby == 2” //do enum class Webcolor { red = 0xFF0000, green = 0x00FF00, blue = 0x0000FF }; enum class Productinfo { red = 0, purple = 1, blue = 2 }; int webby = blue; // error: be specific (this is a class enum, not a plain enum) Webcolor webby = Webcolor::blue;
  • 19.
    Samples: ES.5 Keepscopes small https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es5-keep-scopes-small void use() { int i; // bad: i is needlessly accessible after loop for (i = 0; i < 20; ++i) { /* ... */ } // no intended use of i here // good: i is local to for-loop for (int i = 0; i < 20; ++i) { /* ... */ } // good: pc is local to if-statement if (auto pc = dynamic_cast<Circle*>(ps)) { // ... deal with Circle ... } else { // ... handle error ... } }
  • 20.
    Samples: ES.20 Alwaysinitialize an object https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es20-always-initialize-an-object void use(int arg) { int i; // bad: uninitialized variable // ... i = 7; // initialize i } //No, i = 7 does not initialize i; it assigns to it. //Also, i can be read in the ... part. Better: void use(int arg) { int i = 7; // OK: initialized string s; // OK: default initialized // ... }
  • 21.
    Samples: ES.50 Don'tcast away const https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es50-dont-cast-away-const void bad_function(const MyClass* cInstance) { ... if(cInstance.max_bytes>MAX_VAL) { //bad sample MyClass* instance = const_cast<Myclass*>(cInstance); ++instance.max_bytes; } } //if really needed MyClass can be change, eg: class MyCLass { public: mutable std::int32_t max_bytes; //only a subset can be changed, //not the whole class ... }
  • 22.
    Samples: P.8 Don'tleak any resources https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#p8-dont-leak-any-resources void f(const char* name) { FILE* input = fopen(name, "r"); // ... if (something) return; // bad: A file handle might leak // ... fclose(input); } //Prefer RAII: void f(const char* name) { ifstream input {name}; // ... if (something) return; // OK: no leak // ... }
  • 23.
    Samples: R.5 Don'theap-allocate unnecessarily https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r5-dont-heap-allocate-unnecessarily void f(int n) { auto p = new Gadget{n}; // ... delete p; } //Instead, use a local variable: void f(int n) { Gadget g{n}; // ... }
  • 24.
    Samples: R.11 Avoidcalling new and delete explicitly https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r11-avoid-calling-new-and-delete-explicitly auto myObject = new MyObject{“MyObj”}; //bad auto myObjectUnique = std::make_unique<MyObject>(“MyObj”); //better //in case you need to share the resource in your application: auto myObjectShared = std::make_shared<MyObject>(“MyObj”); //most libraries come with some kind of smart pointers //doing more or less the same (if you cannot use STL)
  • 25.
    Samples: T.1 Usetemplates to raise the level o abstraction of code https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#t1-use-templates-to-raise-the-level-of-abstraction-of-code template<typename T, typename A> // requires Arithmetic<T> A sum(vector<T>& v, A s) { for (auto x : v) s += x; return s; } //For additional generality and reusability, we could also use a //more general Container or Range concept instead of committing to //only one container, vector.
  • 26.
    How can Iuse the GSL?  The GSL has a public specification that can be implemented by anyone  Currently we can use the Microsoft implementation https://github.com/Microsoft/GSL  There are other versions too (eg. for C++11), however not updated very frequently
  • 27.
    Tools to enforcethe rules  A) CppCoreCheck can be installed as package to any C++ project via the following command in the VS package manager console (an then run “Analyze”):  B) Install latest clang from http://llvm.org/releases/download.html and use clang-tidy: (Unfortunately problematic with Windows headers)  Both tools check more than only the C++ Core Guidelines – it’s a good idea in general to use a static code analyzer to avoid errors. PM> Install-Package Microsoft.CppCoreCheck $ clang-tidy SOURCE --checks=all -extra-arg=-std=c++14 –extra-arg=-fexceptions