Saturday 10 August 2013

Starter Kit - C++11

C++11, also formerly known as C++0x,[1] is the name of the most recent iteration of the C++ programming language, approved by ISO as of 12 August 2011, replacing C++03.[2] The name is derived from the tradition of naming language versions by the year of the specification's publication. Changes from the previous version(C++03) of the standard are listed below.

[Core language runtime performance enhancements]

1. Rvalue references and move constructors

In C++03 (and before), temporaries (termed "rvalues", as they often lie on the right side of an assignment) were intended to never be modifiable — just as in C — and were considered to be indistinguishable from const T& types; nevertheless, in some cases, temporaries could have been modified, a behavior that was even considered to be a useful loophole (for the former, see [5]). C++11 adds a new non-const reference type called an rvalue reference, identified by T&&. This refers to temporaries that are permitted to be modified after they are initialized, for the purpose of allowing "move semantics".

A chronic performance problem with C++03 is the costly and unnecessary deep copies that can happen implicitly when objects are passed by value. To illustrate the issue, consider that a std::vector<T> is, internally, a wrapper around a C-style array with a size. If a std::vector<T> temporary is created or returned from a function, it can be stored only by creating a new std::vector<T> and copying all of the rvalue's data into it. Then the temporary and all its memory is destroyed. (For simplicity, this discussion neglects the return value optimization).

In C++11, a "move constructor" of std::vector<T> that takes an rvalue reference to a std::vector<T> can simply copy the pointer to the internal C-style array out of the rvalue into the new std::vector<T>, then set the pointer inside the rvalue to null. Since the temporary will never again be used, no code will try to access the null pointer, and because the pointer is null, its memory is not deleted when it goes out of scope. Hence, the operation not only forgoes the expense of a deep copy, but is safe and invisible.

Rvalue references can provide performance benefits to existing code without needing to make any changes outside the standard library. The type of the returned value of a function returning a std::vector<T> temporary does not need to be changed explicitly to std::vector<T> && to invoke the move constructor, as temporaries are considered rvalues automatically. (However, if std::vector<T> is a C++03 version without a move constructor, then the copy constructor will be invoked with a const std::vector<T>& as normal, incurring a significant memory allocation.)

For safety reasons, some restrictions are imposed. A named variable will never be considered to be an rvalue even if it is declared as such; in order to get an rvalue, the function template std::move<T>() should be used. Rvalue references can also be modified only under certain circumstances, being intended to be used primarily with move constructors.


2. Generalized constant expressions

int get_five() {return 5;}

int some_value[get_five() + 7]; // Create an array of 12 integers. Ill-formed C++

This was not legal in C++03, because get_five() + 7 is not a constant expression. A C++03 compiler has no way of knowing if get_five() actually is constant at runtime. In theory, this function could affect a global variable, call other non-runtime constant functions, etc.

C++11 introduced the keyword constexpr, which allows the user to guarantee that a function or object constructor is a compile-time constant [6]. The above example can be rewritten as follows:

constexpr int get_five() {return 5;}

int some_value[get_five() + 7]; // Create an array of 12 integers. Legal C++11

This allows the compiler to understand, and verify, that get_five is a compile-time constant.

Prior to C++11, the values of variables could be used in constant expressions only if the variables are declared const, have an initializer which is a constant expression, and are of integral or enumeration type. C++11 removes the restriction that the variables must be of integral or enumeration type if they are defined with the constexpr keyword:

constexpr double acceleration_due_to_gravity = 9.8;
constexpr double moon_gravity = acceleration_due_to_gravity / 6.0;

Such data variables are implicitly const, and must have an initializer which must be a constant expression.



[Core language build time performance enhancements]


1. Extern template

In C++03, the compiler must instantiate a template whenever a fully specified template is encountered in a translation unit. If the template is instantiated with the same types in many translation units, this can dramatically increase compile times. There is no way to prevent this in C++03, so C++11 introduced extern template declarations, analogous to extern data declarations.

C++03 has this syntax to oblige the compiler to instantiate a template:

template class std::vector<MyClass>;

C++11 now provides this syntax:

extern template class std::vector<MyClass>;

which tells the compiler not to instantiate the template in this translation unit.


[Core language usability enhancements]


1. Initializer lists

C++11 binds the concept to a template, called std::initializer_list. This allows constructors and other functions to take initializer-lists as parameters. For example:

class SequenceClass {
public:
    SequenceClass(std::initializer_list<int> list);
};

This allows SequenceClass to be constructed from a sequence of integers, as such:

SequenceClass some_var = {1, 4, 5, 6};

This constructor is a special kind of constructor, called an initializer-list-constructor. Classes with such a constructor are treated specially during uniform initialization (see below)

The class std::initializer_list<> is a first-class C++11 standard library type. However, they can be initially constructed statically by the C++11 compiler only through the use of the {} syntax. The list can be copied once constructed, though this is only a copy-by-reference. An initializer list is constant; its members cannot be changed once the initializer list is created, nor can the data in those members be changed.

Because initializer_list is a real type, it can be used in other places besides class constructors. Regular functions can take typed initializer lists as arguments. For example:

void function_name(std::initializer_list<float> list);

function_name({1.0f, -3.45f, -0.4f});

Standard containers can also be initialized in the following ways:

std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" };

 

2. Uniform initialization

C++11 provides a syntax that allows for fully uniform type initialization that works on any object. It expands on the initializer list syntax:

struct BasicStruct {
    int x;
    double y;
};

struct AltStruct {
    AltStruct(int x, double y) : x_{x}, y_{y} {}

private:
    int x_;
    double y_;
};

BasicStruct var1{5, 3.2};
AltStruct var2{2, 4.3};

The initialization of var1 behaves exactly as though it were aggregate-initialization. That is, each data member of an object, in turn, will be copy-initialized with the corresponding value from the initializer-list. Implicit type conversion will be used where necessary. If no conversion exists, or only a narrowing conversion exists, the program is ill-formed. The initialization of var2 invokes the constructor.

One is also able to do the following:

struct IdString {
    std::string name;
    int identifier;
};

IdString get_string()
{
    return {"foo", 42}; //Note the lack of explicit type.
}

Uniform initialization does not replace constructor syntax. There are still times when constructor syntax is required. If a class has an initializer list constructor (TypeName(initializer_list<SomeType>);), then it takes priority over other forms of construction, provided that the initializer list conforms to the sequence constructor's type. The C++11 version of std::vector has an initializer list constructor for its template type. This means that the following code:

std::vector<int> the_vec{4};

will call the initializer list constructor, not the constructor of std::vector that takes a single size parameter and creates the vector with that size. To access the latter constructor, the user will need to use the standard constructor syntax directly.


3. Type Interfaces

C++11 allows to create a variable of the specific type of the initializer:

auto some_strange_callable_type = boost::bind(&some_function, _2, _1, some_object);
auto other_variable = 5;

The type of some_strange_callable_type is simply whatever the particular template function override of boost::bind returns for those particular arguments. This type is easily determined procedurally by the compiler as part of its semantic analysis duties, but is not easy for the user to determine upon inspection.

The type of other_variable is also well-defined, but it is easier for the user to determine. It is an int, which is the same type as the integer literal.

Additionally, the keyword decltype can be used to determine the type of an expression at compile-time. For example:

int some_int;
decltype(some_int) other_integer_variable = 5;

This is more useful in conjunction with auto, since the type of an auto variable is known only to the compiler. However, decltype can also be very useful for expressions in code that makes heavy use of operator overloading and specialized types.

auto is also useful for reducing the verbosity of the code. For instance, instead of writing

for (std::vector<int>::const_iterator itr = myvec.cbegin(); itr != myvec.cend(); ++itr)

the programmer can use the shorter

for (auto itr = myvec.cbegin(); itr != myvec.cend(); ++itr)


4. Range-based for-loop

int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
    x *= 2;
}



5. Lambda functions and expressions

C++11 provides the ability to create anonymous functions, called lambda functions. These are defined as follows:

**********************************
[](int x, int y) { return x + y; }
**********************************

The return type is implicit; it returns the type of the return expression (decltype(x+y)). The return type of a lambda can be omitted so long as all return expressions return the same type.



6. Alternative (template) function syntax

The following, for example, is not allowed in C++03:

template<class Lhs, class Rhs>
  Ret adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;} //Ret must be the type of lhs+rhs

The type Ret is whatever the addition of types Lhs and Rhs will produce. Even with the aforementioned C++11 functionality of decltype, this is not possible:

template<class Lhs, class Rhs>
  decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;} //Not legal C++11

This is not legal C++ because lhs and rhs have not yet been defined; they will not be valid identifiers until after the parser has parsed the rest of the function prototype.

To work around this, C++11 introduced a new function declaration syntax, with a trailing-return-type:

************************************************************
template<class Lhs, class Rhs>
auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;}
************************************************************
This syntax can be used for more mundane function declarations and definitions:

struct SomeStruct  {
    auto func_name(int x, int y) -> int;
};

auto SomeStruct::func_name(int x, int y) -> int {
    return x + y;
}

The use of the keyword “auto” in this case means something different from its use in automatic type deduction.



7. Object construction improvement

C++11 allows constructors to call other peer constructors (known as delegation). This allows constructors to utilize another constructor's behavior with a minimum of added code. Examples of other languages similar to C++ that provide delegation are Java, C#, and D.

This syntax is as follows:

class SomeType  {
    int number;

public:
    SomeType(int new_number) : number(new_number) {}
    SomeType() : SomeType(42) {}
};

This comes with a caveat: C++03 considers an object to be constructed when its constructor finishes executing, but C++11 considers an object constructed once any constructor finishes execution. Since multiple constructors will be allowed to execute, this will mean that each delegate constructor will be executing on a fully constructed object of its own type. Derived class constructors will execute after all delegation in their base classes is complete.

For base-class constructors, C++11 allows a class to specify that base class constructors will be inherited. This means that the C++11 compiler will generate code to perform the inheritance, the forwarding of the derived class to the base class. Note that this is an all-or-nothing feature; either all of that base class's constructors are forwarded or none of them are. Also, note that there are restrictions for multiple inheritance, such that class constructors cannot be inherited from two classes that use constructors with the same signature. Nor can a constructor in the derived class exist that matches a signature in the inherited base class.

The syntax is as follows:

class BaseClass {
public:
    BaseClass(int value);
};

class DerivedClass : public BaseClass {
public:
    using BaseClass::BaseClass;
};

For member initialization, C++11 allows the following syntax:

class SomeClass {
public:
    SomeClass() {}
    explicit SomeClass(int new_value) : value(new_value) {}

private:
    int value = 5;
};

Any constructor of the class will initialize value with 5, if the constructor does not override the initialization with its own. So the above empty constructor will initialize value as the class definition states, but the constructor that takes an int will initialize it to the given parameter.

It can also use constructor or uniform initialization, instead of the equality initialization shown above.



8. Explicit overrides and final

In C++03, it is possible to accidentally create a new virtual function, when one intended to override a base class function. For example:

struct Base {
    virtual void some_func(float);
};

struct Derived : Base {
    virtual void some_func(int);
};

The Derived::some_func is intended to replace the base class version. But because it has a different interface, it creates a second virtual function. This is a common problem, particularly when a user goes to modify the base class.

C++11 provides syntax to solve this problem.

struct Base {
    virtual void some_func(float);
};

struct Derived : Base {
    virtual void some_func(int) override; // ill-formed because it doesn't override a base class method
};

The override special identifier means that the compiler will check the base class(es) to see if there is a virtual function with this exact signature. And if there is not, the compiler will error out.

C++11 also adds the ability to prevent inheriting from classes or simply preventing overriding methods in derived classes. This is done with the special identifier final. For example:

struct Base1 final { }; ---------------------- IMPORTANT

struct Derived1 : Base1 { }; // ill-formed because the class Base1 has been marked final

struct Base2 {
    virtual void f() final;
};

struct Derived2 : Base2 {
    void f(); // ill-formed because the virtual function Base2::f has been marked final
};

In this example, the virtual void f() final; statement declares a new virtual function, but it also prevents derived classes from overriding it. It also has the effect of preventing derived classes from using that particular function name and parameter combination.

Note that neither override nor final are language keywords. They are technically identifiers; they gain special meaning only when used in those specific contexts. In any other location, they can be valid identifiers.

 

9. Null pointer constant

void foo(char *);
void foo(int);

If NULL is defined as 0 (which is usually the case in C++), the statement foo(NULL); will call foo(int), which is almost certainly not what the programmer intended, and not what a superficial reading of the code suggests.

C++11 corrects this by introducing a new keyword to serve as a distinguished null pointer constant: nullptr. It is of type nullptr_t, which is implicitly convertible and comparable to any pointer type or pointer-to-member type. It is not implicitly convertible or comparable to integral types, except for bool. While the original proposal specified that an rvalue of type nullptr should not be convertible to bool, the core language working group decided that such a conversion would be desirable, for consistency with regular pointer types. The proposed wording changes were unanimously voted into the Working Paper in June 2008.[2]

For backwards compatibility reasons, 0 remains a valid null pointer constant.

char *pc = nullptr;     // OK
int  *pi = nullptr;     // OK
bool   b = nullptr;     // OK. b is false.
int    i = nullptr;     // error ------------------------------- IMPORTANT, this is the idea.

foo(nullptr);           // calls foo(char *), not foo(int);



10. Strongly typed enumerations

In C++03, enumerations are not type-safe. They are effectively integers, even when the enumeration types are distinct. This allows the comparison between two enum values of different enumeration types. The only safety that C++03 provides is that an integer or a value of one enum type does not convert implicitly to another enum type. Additionally, the underlying integral type is implementation-defined; code that depends on the size of the enumeration is therefore non-portable. Lastly, enumeration values are scoped to the enclosing scope. Thus, it is not possible for two separate enumerations to have matching member names.

C++11 allows a special classification of enumeration that has none of these issues. This is expressed using the enum class (enum struct is also accepted as a synonym) declaration:

enum class Enumeration {
    Val1,
    Val2,
    Val3 = 100,
    Val4 // = 101
};

This enumeration is type-safe. Enum class values are not implicitly converted to integers; therefore, they cannot be compared to integers either (the expression Enumeration::Val4 == 101 gives a compiler error).


11. Right angle bracket

C++03's parser defines “>>” as the right shift operator in all cases. However, with nested template declarations, there is a tendency for the programmer to neglect to place a space between the two right angle brackets, thus causing a compiler syntax error.

C++11 improves the specification of the parser so that multiple right angle brackets will be interpreted as closing the template argument list where it is reasonable. This can be overridden by using parentheses:

template<bool Test> class SomeType;
std::vector<SomeType<1>2>> x1;  // Interpreted as a std::vector of SomeType<true> 2>,
// which is not legal syntax. 1 is true.
std::vector<SomeType<(1>2)>> x1;  // Interpreted as std::vector of SomeType<false>,
// which is legal C++11 syntax. (1>2) is false.


[Core language functionality improvements]


1. Variadic templates

Prior to C++11, templates (classes and functions) can only take a fixed number of arguments that have to be specified when a template is first declared. C++11 allows template definitions to take an arbitrary number of arguments of any type.

*****************************************
template<typename... Values> class tuple;
*****************************************

This template class tuple will take any number of typenames as its template parameters:

***************************************************
tuple<int, std::vector<int>, std::map<std::string, std::vector<int>>> some_instance_name;
***************************************************

The number of arguments can be zero, so tuple<> some_instance_name; will work as well.

If one does not want to have a variadic template that takes 0 arguments, then this definition will work as well:

template<typename First, typename... Rest> class tuple;

Variadic templates may also apply to functions, thus not only providing a type-safe add-on to variadic functions (such as printf) - but also allowing a printf-like function to process non-trivial objects.

template<typename... Params> void printf(const std::string &str_format, Params... parameters);

The ... operator has two roles. When it occurs to the left of the name of a parameter, it declares a parameter pack. By using the parameter pack, user can bind zero or more arguments to the variadic template parameters. Parameter packs can also be used for non-type parameters. By contrast, when the ... operator occurs to the right of a template or function call argument, it unpacks the parameter packs into separate arguments, like the args... in the body of printf below. In practice, the use of ... operator in the code causes that the whole expression that precedes the ... operator, will be repeated for every next argument unpacked from the argument pack, and all these expressions will be separated by a comma.

The use of variadic templates is often recursive. The variadic parameters themselves are not readily available to the implementation of a function or class. Therefore, the typical mechanism for defining something like a C++11 variadic printf replacement would be as follows:

void printf(const char *s)
{
    while (*s) {
        if (*s == '%' && *(++s) != '%')
            throw std::runtime_error("invalid format string: missing arguments");
        std::cout << *s++;
    }
}

***********************************************************************************
template<typename T, typename... Args>
void printf(const char *s, T value, Args... args)
{
    while (*s) {
        if (*s == '%' && *(++s) != '%') {
            std::cout << value;
            ++s;
            printf(s, args...); // call even when *s == 0 to detect extra arguments
            return;
        }
        std::cout << *s++;
    }
    throw std::logic_error("extra arguments provided to printf");
}
***********************************************************************************

 

2. Thread-local storage

In a multi-threaded environment, it is common for every thread to have some unique variables. This already happens for the local variables of a function, but it does not happen for global and static variables.

A new thread-local storage duration (in addition to the existing static, dynamic and automatic) is indicated by the storage specifier thread_local.

Any object which could have static storage duration (i.e., lifetime spanning the entire execution of the program) may be given thread-local duration instead. The intent is that like any other static-duration variable, a thread-local object can be initialized using a constructor and destroyed using a destructor.



3. Explicitly defaulted and deleted special member functions

C++11 allows the explicit defaulting and deleting of these special member functions. For example, the following type explicitly declares that it is using the default constructor:

struct SomeType {
    SomeType() = default; //The default constructor is explicitly stated.
    SomeType(OtherType value);
};

Alternatively, certain features can be explicitly disabled. For example, the following type is non-copyable:

struct NonCopyable {
    NonCopyable & operator=(const NonCopyable&) = delete;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable() = default;
};

The = delete specifier can be used to prohibit calling any function, which can be used to disallow calling a member function with particular parameters. For example:

struct NoInt {
    void f(double i);
    void f(int) = delete;
};

An attempt to call f() with an int will be rejected by the compiler, instead of performing a silent conversion to double. This can be generalized to disallow calling the function with any type other than double as follows:

struct OnlyDouble {
    void f(double d);
    template<class T> void f(T) = delete;
};


4. Type long long int

In C++03, the largest integral type is long int. It is guaranteed to have at least as many usable bits as int. This resulted in long int having size of 64 bits on some popular implementations and 32 bits on others. C++11 adds a new integral type long long int to address this issue. It is guaranteed to be at least as large as a long int, and have no fewer than 64 bits.


5. Static assertions

C++03 provides two methods to test assertions: the macro assert and the preprocessor directive #error. However, neither is appropriate for use in templates: the macro tests the assertion at execution-time, while the preprocessor directive tests the assertion during preprocessing, which happens before instantiation of templates. Neither is appropriate for testing properties that are dependent on template parameters.

The new utility introduces a new way to test assertions at compile-time, using the new keyword static_assert. The declaration assumes the following form:

static_assert (constant-expression, error-message);

Here are some examples of how static_assert can be used:

****************************************************
static_assert ((GREEKPI > 3.14) && (GREEKPI < 3.15), 

"GREEKPI is inaccurate!");
****************************************************

template<class T>
struct Check  {
    static_assert (sizeof(int) <= sizeof(T), "T is not big enough!");
};

Allow sizeof to work on members of classes without an explicit object

In C++03, the sizeof operator can be used on types and objects. But it cannot be used to do the following:

struct SomeType { OtherType member; };

sizeof(SomeType::member); //Does not work with C++03. Okay with C++11


 

6. Threading facilities

While the C++11 language provides a memory model that supports threading, the primary support for actually using threading comes with the C++11 standard library.

A thread class (std::thread) is provided which takes a function object — and an optional series of arguments to pass to it — to run in the new thread. It is possible to cause a thread to halt until another executing thread completes, providing thread joining support through the std::thread::join() member function. Access is provided, where feasible, to the underlying native thread object(s) for platform specific operations by the std::thread::native_handle() member function.

For synchronization between threads, appropriate mutexes (std::mutex, std::recursive_mutex, etc.) and condition variables (std::condition_variable and std::condition_variable_any) are added to the library. These are accessible through RAII locks (std::lock_guard and std::unique_lock) and locking algorithms for easy use.


 

8. Tuple types

Tuples are collections composed of heterogeneous objects of pre-arranged dimensions. A tuple can be considered a generalization of a struct's member variables.

Using variadic templates, the declaration of the tuple class looks as follows:

******************************************************************
template <class ...Types> class tuple;

typedef std::tuple <int , double, string       > tuple_1 t1;
typedef std::tuple <char, short , const char * > tuple_2 t2 ('X', 2, "Hola!");
t1 = t2 ;  // Ok, first two elements can be converted,
           // the third one can be constructed from a 'const char *'.
******************************************************************

Relational operators are available (among tuples with the same number of elements), and two expressions are available to check a tuple’s characteristics (only during compilation):

    std::tuple_size<T>::value returns the number of elements in the tuple T,
    std::tuple_element<I, T>::type returns the type of the object number I of the tuple T.

 

9. Hash tables

The new library has four types of hash tables, differentiated by whether or not they accept elements with the same key (unique keys or equivalent keys), and whether they map each key to an associated value. They correspond to the four existing binary-search-tree-based associative containers, with an unordered_ prefix.

Type of hash table     Associated values     Equivalent keys

std::unordered_set         No         No
std::unordered_multiset     No         Yes
std::unordered_map         Yes         No
std::unordered_multimap     Yes         Yes

New classes fulfill all the requirements of a container class, and have all the methods necessary to access elements: insert, erase, begin, end.

 

10. Regular expressions

The new library, defined in the new header <regex>, is made of a couple of new classes:

    regular expressions are represented by instance of the template class std::regex;
    occurrences are represented by instance of the template class std::match_results.

The function std::regex_search is used for searching, while for ‘search and replace’ the function std::regex_replace is used which returns a new string. The algorithms std::regex_search and std::regex_replace take a regular expression and a string and write the occurrences found in the struct std::match_results.

Here is an example of the use of std::match_results:

const char *reg_esp = "[ ,.\\t\\n;:]";  // List of separator characters.

// this can be done using raw string literals:
// const char *reg_esp = R"([ ,.\t\n;:])";

std::regex rgx(reg_esp);  // 'regex' is an instance of the template class
                      // 'basic_regex' with argument of type 'char'.
std::cmatch match;  // 'cmatch' is an instance of the template class
                // 'match_results' with argument of type 'const char *'.
const char *target = "Unseen University - Ankh-Morpork";

// Identifies all words of 'target' separated by characters of 'reg_esp'.
if( std::regex_search( target, match, rgx ) ) {
    // If words separated by specified characters are present.

    const size_t n = match.size();
    for( size_t a = 0; a < n; a++ ) {
        std::string str( match[a].first, match[a].second );
        std::cout << str << "\n";
    }
}

Note the use of double backslashes, because C++ uses backslash as an escape character. The C++11 raw string feature could be used to avoid the problem.

The library <regex> requires neither alteration of any existing header (though it will use them where appropriate) nor an extension of the core language.

 

11. General-purpose smart pointers

C++11 provides std::unique_ptr, as well as improvements to std::shared_ptr and std::weak_ptr from TR1. std::auto_ptr is deprecated.

 

12. Wrapper reference

A wrapper reference is obtained from an instance of the template class reference_wrapper. Wrapper references are similar to normal references (‘&’) of the C++ language. To obtain a wrapper reference from any object the function template ref is used (for a constant reference cref is used).

Wrapper references are useful above all for function templates, where references to parameters rather than copies are needed:

// This function will obtain a reference to the parameter 'r' and increment it.
void f (int &r)  { r++; }

// Template function.
template<class F, class P> void g (F f, P t)  { f(t); }

int main()
{
    int i = 0 ;
    g (f, i) ;  // 'g<void (int &r), int>' is instantiated
               // then 'i' will not be modified.
    std::cout << i << std::endl;  // Output -> 0

    g (f, std::ref(i));  // 'g<void(int &r),reference_wrapper<int>>' is instantiated
                    // then 'i' will be modified.
    std::cout << i << std::endl;  // Output -> 1
}

 

13. Polymorphic wrappers for function objects

Polymorphic wrappers for function objects are similar to function pointers in semantics and syntax, but are less tightly bound and can indiscriminately refer to anything which can be called (function pointers, member function pointers, or functors) whose arguments are compatible with those of the wrapper.

Through the example it is possible to understand its characteristics:

std::function<int (int, int)> func;  // Wrapper creation using
                                 // template class 'function'.
std::plus<int> add;  // 'plus' is declared as 'template<class T> T plus( T, T ) ;'
                 // then 'add' is type 'int add( int x, int y )'.
func = add;  // OK - Parameters and return types are the same.

int a = func (1, 2);  // NOTE: if the wrapper 'func' does not refer to any function,
                      // the exception 'std::bad_function_call' is thrown.
This new utility was added to the existing <utility> header and didn't need further extensions of the C++ language.

 

 

-----------------

C++11 in nutshell

-----------------


General
    RValue reference and move construct
    constexpr
    initialization list
    auto keyword
        auto as function return type
        auto as iterators
    for loop
        for(int &x: my_array)
    Derived's class constructor can base class constructor
        use base class construtor by using Base::Base
    Override - virtual function
    Final - Disallow class inheritance
    nullptr
    thread_local storage for globals and static
    default - constructor
    delete - copy constructor, operator=
    4 types of hashtables
    regex
        std::regex
        std::match_result   
        std::cmatch instance of std::match_result
        std::regexsearch(target, match, regx)
    unique_ptr IN and auto_ptr OUT
    std::ref to get reference from object
        int i;
        std::ref(i);

Templates
    extern
        to avoid particular type instantiation.
    auto
        template<typename RHS, typename LHS>
        auto funtion_my( RHS r, LHS l) -> decltype(r + l) {return r + l; }
    variadic template
        template <typename... T>
        my_fun(T... t)
    std::tupple
    static_assert

No comments:

Post a Comment