References
[1] Bjarne Stroustrup. A Tour C++ Second Edition 2018 http://www.stroustrup.com/tour2.html
[2] Syntax highlighting https://tohtml.com/
[3] Bjarne Stroustrup. The C++ Programming Language (4th Edition) 2013 http://www.stroustrup.com/4th.html
[4] The continuing evolution of C++. Bjarne Stroustrup https://www.youtube.com/watch?v=ooehrkYkGdA
C++ Standards history
1. C++1998 standard - ISO/IEC 14882-1998
2. C++2003 standard - A “bug fix release” of this standard was issued in 2003
3. C++2011 standard - ISO C++ standard (ISO/IEC 14882-2011)
4. C++2014 standard - ISO C++ standard (ISO/IEC 14882:2014) - completes C++11 and fix various issues in it
5. C++2017 standard - ISO C++ standard (ISO/IEC 14882:2017)
6. С++2020 standart - Future
Principles
Principles of language which B.Stroustroup put into the language in 1994 are still actual and the language still following it. [4]
Some of them:
a. No implicit violation of static type-system
b. Provide good support for user-defined types similar to built-in types
c. The locality is good
d. Zero-Overhead principle
- What you don't use - you should not pay for
- If something built-in in the language then it's impossible to write it better by hand
List of features
struct Entry { string name; int value; };auto [n,v] = read_entry(is)
The "auto [n,v]" declares two local variables n and v with their types deduced from read_entry() return type.
This mechanism for giving local names to members of a class object is named as a structured binding.
Modules will come from C++20 to upgrade the understanding of header files. And there are reasons to include it in standards.
In [4] B.Stroustroup mentions two things:
- Google reports x2-4 improvements in compile-time
- Microsoft reports x5-x50 times improvements in compile time
//================================
//OLD C++ TEXT <=> NEW C++ TEXT
//================================
#include <iostream> <=> import iostream
namespace My <=> module mymodule;
template <class T> <=> export template <class T>
void f(){} <=> void f(){}
1. The use of override is optional, but being explicit allows the compiler to catch mistakes, such as misspellings of function names or slight differences between the type of a virtual function.
2. So it can be a situation when the function is intended to override something, but due to mistake, it is a new virtual function. But in the case of using "override" will remove this problem.
2. Better to not repeat virtual in a derived class, but if you want to be explicit use "override"
3. final provides prevent further overriding
4. B.Stroustroup said:
"That it’s illogical that virtual is a prefix and override is a suffix. This is part of the price we pay for compatibility and stability over the decades.
Curiously, override is not a keyword; it is what is called a contextual keyword. E.g. It can be used as an identifier."
struct Base { Base(){puts("Base()");} Base(const Base&){puts("Base(const Base&)");} virtual void f(){} // declare functions in a base class that can be redefined in each derived class virtual void g(){} // declare functions in a base class that can be redefined in each derived class }; struct A: Base { A(){puts(__func__);} A(const A&a): Base(a) {puts("A(const A&)");} virtual void f(){} // By default, a function that overrides a virtual function itself becomes virtual void g(){} // By default, a function that overrides a virtual function itself becomes virtual}; struct B: Base { B(){puts(__func__);}; B(const B& b) : Base(b) {puts("B(const B&)");} // Better to not repeat virtual in a derived class, but if you want be explicit use "override" // final provides prevent further overriding void f() override final {} int override = 7;};
4. Some class operators (C++11)
class X { public: X(Sometype); // "ordinary constructor": create an object X(); // Default constructor X(const X&); // Copy constructor X(X&&); // Move constructor X& operator=(const X&); // Copy assignment: clean up target and copy X& operator=(X&&); // Move assignment: clean up target and move ~X(); // Destructor: clean up};
5. Default Member Initializers (C++11)
When a data member of a class is defined, we can supply a default initializer called a default member initializer.
The default value is used whenever a constructor doesn’t provide a value.
This simplifies code and helps us to avoid accidentally leaving a member uninitialized.
class X { int i = 4; int j {5};};
6. User-defined literals or UDLs (C++11)
Unsurprisingly, literals with user-defined suffixes are called user-defined literals or UDL.
long double operator "" _w(long double);int main() { 1.2w; // calls operator "" _w(1.2L)}
7. Constrained Template Arguments (C++20)
template<Element T> class Vector {private: T* elem; // elem points to an array of sz elements of type T int sz; // ... };
Element is a predicate that checks whether T has all the properties that a templace class Vector requires.
Such predicate is called a concept. Concepts are going to be compile-time predicate.
Concepts will make possible to create requirement on template arguments.
For example it can be used to define the requirement for the type, such that during template function writing we can specify the requirement for input type.
8. Deduce template parameters from constructor arguments (from C++17)
// Example program#include <iostream>#include <string>template <class T>class A {public: A(T arg) { (void)arg; }}; A a(123); // Valid from C++17! Before C++17 such feature was supported only for template functions, but not for template classes!!!
9. Compile-Time If (C++17)
Only the selected branch of an if constexpr is instantiated.
This solution offers optimal performance and locality of the optimization.
// Example program#include <iostream>#include <string>#include <type_traits>template<typename T> void update(T& target) { if constexpr(std::is_pod<T>::value) simple_and_fast(target); // for "plain old data" else slow_and_safe(target); // ... }int main(){ return 0;}
10. Library improvements
11. Template Type Deduction from Arguments
A compiler can deduce a type template argument from a template function argument with a type even a type is composed of the following constructs from template type.
12. constexpr
constexpr - indicating that it should be possible to evaluate the function at compile time if given constant expressions as arguments.
The main idea due to B.Stroustroup is that it brings type-rich programming in compile-time.
The deep reason that includes this into language lies in that a lot of communities ask B.Stroustroup to include in languages something which will make table-lookup easier.
And because it's near impossible to be faster than table lookup then this concept can make sense.
C++11 constexpr functions had to put everything in a single return statement
C++14 constexpr functions, not necessarily had to put everything in a single return statement
Code example:
constexpr int sum(int a, int b) { return a + b; }
A const differs from a constexpr.
const - can be initialized by something that is not a constant expression.
constexpr - can be conceptually initialized only by const
constexpr int a = 12;
13. Some language rules which are still valid from ANSI C89 or C++1998
1. A string literal is statically allocated so that it is safe to return one from a function
2. Names starting with a double underscore (__) or an underscore followed by an uppercase letter (e.g., _Foo) are reserved by the compiler implementations.
3. In C++11 export is reserved for future uses
4. Few machines can directly address an individual bit. Even if the machine allows to do it - then it is out of the scope of C/C++, to be honest. (Of course - you can operate on bits, but not directly)
5. Notes about terminology about casting: Upcast - cast to the base class, Downcast - cast to the derived class.
6. To get runtime polymorphic behavior the member functions must be virtual and objects must be manipulated through pointers or references.
Calling a function using the scope resolution "operator ::" ensures that the virtual mechanism which is builtin in the language is not using.
7. When manipulating an object directly (rather than through a pointer or references) and its exact type is known by the compiler then
in that case, run-time polymorphism is not needed and the call will be done without using vptr's.
8. A virtual function invoked from a constructor or a destructor reflects that the object is partially constructed
9. There is a language rule that says that such a substitution failure is not an error. It simply causes the template to be ignored.
10. B.Stroustroup doesn’t consider it a good idea to provide individual access to all members of a class.
11. Due to B.Stroustroup for many types, individual access (sometimes referred to as get-and-set functions) is an invitation to disaster.
14. Some language rules which are specific for C++11 and upper
1. Bracket/Uniform initialization via using {} in form of list initialization does not allow narrowing
auto x1 = {1,2,3,4}; // x1 is an initializer_list<int>
2. In C++11 export is reserved for future uses
3. Several C99 features included into C++11 and above officially:
__func__ -- a string containing the incomplete and undecorated name of the enclosing function
vararg macros -- #define eprintf(…) fprintf (stderr, __VA_ARGS__)
15. [[noreturn]] attribute (C++11)
Placing [[noreturn]] at the start of a function declaration indicates that the function is not expected to return.
Anoter attributes in C++17/C++20: attributes
struct S {
[[noreturn]] virtual inline auto f(const unsigned long int* arg)-> void const {}
};
For example use case [[noreturn]] void exit(int);
16. [[deprecated]] attribute (C++14)
This indicates that the use of the name or entity declared with this attribute is allowed, but discouraged for some reason.
Compilers typically issue warnings. For example use case [[deprecated]] void func(int);
17. noexcept modifier (C++11)
An empty exception specification throw() is defined to be equivalent to noexcept
void g1(int) throw() {}
void g2(int) noexcept {}
18. alignof operator (C++11)
std::cout << alignof('c'); // print alignment for char's
19. alignas operator (C++11)
// allocate a buffer in a stack with the requirement to allocate it with alignment suitable for type "int"
alignas(int) char buff[1024];
20. Raw String Literal (C++11)
std::cout << R"(Raw string literal no backslash for \ or )";
21. Anonymous unions (C++11)
union {
float f;
uint32_t d;
};
f = 3.14f;
22. Type Alias (C++11)
namespace AA = std; // Usual namespace alias from C++98.
typedef AA::vector<int> VecInt1; // Usual typedef
using VecInt2 = AA::vector<int>; // Alias for bind some types. From C++11
23. Return Type Deduction (C++14)
auto f() {
return 42;
}
24. Binary Literals (C++14)
unsigned char a = 0b00110011;
25. Future possible feature - Contract (Maybe will be C++20)
Something like general asserts. Specification on:
1. What invariants we're waiting to hold when function starts
2. What invariants we're waiting to hold when function ends
3. Include invariant checks in fucntion body
void push(queue& q)
[[expects: !q.isFull()]]
[[ensures: !q.isEmpty()]]
{
[[asserts: q.isOk()]]
}
26. Future possible feature - Coroutine (C++20)