Overload Assignment Operator C++ Template Typedef

C++11 is a version of the standard for the programming language C++. It was approved by International Organization for Standardization (ISO) on 12 August 2011, replacing C++03,[1] superseded by C++14 on 18 August 2014[2] and later, by C++17. The name follows the tradition of naming language versions by the publication year of the specification, though it was formerly named C++0x because it was expected to be published before 2010.[3]

Although one of the design goals was to prefer changes to the libraries over changes to the core language,[4] C++11 does make several additions to the core language. Areas of the core language that were significantly improved include multithreading support, generic programming support, uniform initialization, and performance. Significant changes were also made to the C++ Standard Library, incorporating most of the C++ Technical Report 1 (TR1) libraries, except the library of mathematical special functions.[5]

C++11 was published as ISO/IEC 14882:2011[6] in September 2011 and is available for a fee. The working draft most similar to the published C++11 standard is N3337, dated 16 January 2012;[7] it has only editorial corrections from the C++11 standard.[8]

Design goals[edit]

The design committee attempted to stick to a number of goals in designing C++11:

  • Maintain stability and compatibility with C++98 and possibly with C
  • Prefer introducing new features via the standard library, rather than extending the core language
  • Prefer changes that can evolve programming technique
  • Improve C++ to facilitate systems and library design, rather than introduce new features useful only to specific applications
  • Increase type safety by providing safer alternatives to earlier unsafe techniques
  • Increase performance and the ability to work directly with hardware
  • Provide proper solutions for real-world problems
  • Implement zero-overhead principle (further support needed by some utilities must be used only if the utility is used)
  • Make C++ easy to teach and to learn without removing any utility needed by expert programmers

Attention to beginners is considered important, because most computer programmers will always be such, and because many beginners never widen their knowledge, limiting themselves to work in aspects of the language in which they specialize.[1]

Extensions to the C++ core language[edit]

One function of the C++ committee is the development of the language core. Areas of the core language that were significantly improved include multithreading support, generic programming support, uniform initialization, and performance.

Core language runtime performance enhancements[edit]

These language features primarily exist to provide some kind of performance benefit, either of memory or of computational speed.[citation needed]

Rvalue references and move constructors[edit]

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 types; nevertheless, in some cases, temporaries could have been modified, a behavior that was even considered to be a useful loophole.[9] C++11 adds a new non-const reference type called an rvalue reference, identified by . 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 unneeded deep copies that can happen implicitly when objects are passed by value. To illustrate the issue, consider that an is, internally, a wrapper around a C-style array with a size. If an temporary is created or returned from a function, it can be stored only by creating a new and copying all 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 that takes an rvalue reference to an can copy the pointer to the internal C-style array out of the rvalue into the new , 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 an temporary does not need to be changed explicitly to to invoke the move constructor, as temporaries are considered rvalues automatically. (However, if is a C++03 version without a move constructor, then the copy constructor will be invoked with an , 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. To get an rvalue, the function template should be used. Rvalue references can also be modified only under certain circumstances, being intended to be used primarily with move constructors.

Due to the nature of the wording of rvalue references, and to some modification to the wording for lvalue references (regular references), rvalue references allow developers to provide perfect function forwarding. When combined with variadic templates, this ability allows for function templates that can perfectly forward arguments to another function that takes those particular arguments. This is most useful for forwarding constructor parameters, to create factory functions that will automatically call the correct constructor for those particular arguments. This is seen in the emplace_back set of the C++ standard library methods.

constexpr – Generalized constant expressions[edit]

C++ has always had the concept of constant expressions. These are expressions such as that will always yield the same results, at compile time and at run time. Constant expressions are optimization opportunities for compilers, and compilers frequently execute them at compile time and hardcode the results in the program. Also, in several places, the C++ specification requires using constant expressions. Defining an array requires a constant expression, and enumerator values must be constant expressions.

However, a constant expression has never been allowed to contain a function call or object constructor. So a piece of code as simple as this is invalid:

intget_five(){return5;}intsome_value[get_five()+7];// Create an array of 12 integers. Ill-formed C++

This was not valid in C++03, because is not a constant expression. A C++03 compiler has no way of knowing if 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 , which allows the user to guarantee that a function or object constructor is a compile-time constant.[10] The above example can be rewritten as follows:

constexprintget_five(){return5;}intsome_value[get_five()+7];// Create an array of 12 integers. Valid C++11

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

Using on a function imposes some limits on what that function can do. First, the function must have a non-void return type. Second, the function body cannot declare variables or define new types. Third, the body may contain only declarations, null statements and a single return statement. There must exist argument values such that, after argument substitution, the expression in the return statement produces a constant expression.

Before 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 keyword:

constexprdoubleearth_gravitational_acceleration=9.8;constexprdoublemoon_gravitational_acceleration=earth_gravitational_acceleration/6.0;

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

To construct constant expression data values from user-defined types, constructors can also be declared with . A constructor's function body can contain only declarations and null statements, and cannot declare variables or define types, as with a function. There must exist argument values such that, after argument substitution, it initializes the class's members with constant expressions. The destructors for such types must be trivial.

The copy constructor for a type with any constructors should usually also be defined as a constructor, to allow objects of the type to be returned by value from a constexpr function. Any member function of a class, such as copy constructors, operator overloads, etc., can be declared as , so long as they meet the requirements for constexpr functions. This allows the compiler to copy objects at compile time, perform operations on them, etc.

If a constexpr function or constructor is called with arguments which aren't constant expressions, the call behaves as if the function were not constexpr, and the resulting value is not a constant expression. Likewise, if the expression in the return statement of a constexpr function does not evaluate to a constant expression for a given invocation, the result is not a constant expression.

Modification to the definition of plain old data[edit]

In C++03, a class or struct must follow a number of rules for it to be considered a plain old data (POD) type. Types that fit this definition produce object layouts that are compatible with C, and they could also be initialized statically. The C++03 standard has restrictions on what types are compatible with C or can be statically initialized despite there being no technical reason a compiler couldn't accept the program; if someone were to create a C++03 POD type and add a non-virtual member function, this type would no longer be a POD type, could not be statically initialized, and would be incompatible with C despite no change to the memory layout.

C++11 relaxed several of the POD rules, by dividing the POD concept into two separate concepts: trivial and standard-layout.

A type that is trivial can be statically initialized. It also means that it is valid to copy data around via , rather than having to use a copy constructor. The lifetime of a trivial type begins when its storage is defined, not when a constructor completes.

A trivial class or struct is defined as one that:

  1. Has a trivial default constructor. This may use the default constructor syntax ().
  2. Has trivial copy and move constructors, which may use the default syntax.
  3. Has trivial copy and move assignment operators, which may use the default syntax.
  4. Has a trivial destructor, which must not be virtual.

Constructors are trivial only if there are no virtual member functions of the class and no virtual base classes. Copy/move operations also require all non-static data members to be trivial.

A type that is standard-layout means that it orders and packs its members in a way that is compatible with C. A class or struct is standard-layout, by definition, provided:

  1. It has no virtual functions
  2. It has no virtual base classes
  3. All its non-static data members have the same access control (public, private, protected)
  4. All its non-static data members, including any in its base classes, are in the same one class in the hierarchy
  5. The above rules also apply to all the base classes and to all non-static data members in the class hierarchy
  6. It has no base classes of the same type as the first defined non-static data member

A class/struct/union is considered POD if it is trivial, standard-layout, and all of its non-static data members and base classes are PODs.

By separating these concepts, it becomes possible to give up one without losing the other. A class with complex move and copy constructors may not be trivial, but it could be standard-layout and thus interoperate with C. Similarly, a class with public and private non-static data members would not be standard-layout, but it could be trivial and thus -able.

Core language build-time performance enhancements[edit]

Extern template[edit]

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:

templateclassstd::vector<MyClass>;

C++11 now provides this syntax:

externtemplateclassstd::vector<MyClass>;

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

Core language usability enhancements[edit]

These features exist for the primary purpose of making the language easier to use. These can improve type safety, minimize code repetition, make erroneous code less likely, etc.

Initializer lists[edit]

C++03 inherited the initializer-list feature from C. A struct or array is given a list of arguments in braces, in the order of the members' definitions in the struct. These initializer-lists are recursive, so an array of structs or struct containing other structs can use them.

structObject{floatfirst;intsecond;};Objectscalar={0.43f,10};//One Object, with first=0.43f and second=10ObjectanArray[]={{13.4f,3},{43.28f,29},{5.934f,17}};//An array of three Objects

This is very useful for static lists, or initializing a struct to some value. C++ also provides constructors to initialize an object, but they are often not as convenient as the initializer list. However, C++03 allows initializer-lists only on structs and classes that conform to the Plain Old Data (POD) definition; C++11 extends initializer-lists, so they can be used for all classes including standard containers like .

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

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

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

SequenceClasssome_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 is a first-class C++11 standard library type. However, they can be initially constructed statically by the C++11 compiler only via 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:

voidfunction_name(std::initializer_list<float>list);function_name({1.0f,-3.45f,-0.4f});

Standard containers can also be initialized in these ways:

std::vector<std::string>v={"xyzzy","plugh","abracadabra"};std::vector<std::string>v({"xyzzy","plugh","abracadabra"});std::vector<std::string>v{"xyzzy","plugh","abracadabra"};// see "Uniform initialization" below

Uniform initialization[edit]

C++03 has a number of problems with initializing types. Several ways to do this exist, and some produce different results when interchanged. The traditional constructor syntax, for example, can look like a function declaration, and steps must be taken to ensure that the compiler's most vexing parse rule will not mistake it for such. Only aggregates and POD types can be initialized with aggregate initializers (using ).

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

structBasicStruct{intx;doubley;};structAltStruct{AltStruct(intx,doubley):x_{x},y_{y}{}private:intx_;doubley_;};BasicStructvar1{5,3.2};AltStructvar2{2,4.3};

The initialization of 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 needed. If no conversion exists, or only a narrowing conversion exists, the program is ill-formed. The initialization of invokes the constructor.

One can also do this:

structIdString{std::stringname;intidentifier;};IdStringget_string(){return{"foo",42};//Note the lack of explicit type.}

Uniform initialization does not replace constructor syntax, which is still needed at times. If a class has an initializer list constructor (), 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 has an initializer list constructor for its template type. Thus this code:

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

will call the initializer list constructor, not the constructor of 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.

Type inference[edit]

In C++03 (and C), to use a variable, its type must be specified explicitly. However, with the advent of template types and template metaprogramming techniques, the type of something, particularly the well-defined return value of a function, may not be easily expressed. Thus, storing intermediates in variables is difficult, possibly needing knowledge of the internals of a given metaprogramming library.

C++11 allows this to be mitigated in two ways. First, the definition of a variable with an explicit initialization can use the keyword.[11][12] This creates a variable of the specific type of the initializer:

autosome_strange_callable_type=std::bind(&some_function,_2,_1,some_object);autoother_variable=5;

The type of is simply whatever the particular template function override of 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 is also well-defined, but it is easier for the user to determine. It is an , which is the same type as the integer literal.

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

intsome_int;decltype(some_int)other_integer_variable=5;

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

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

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

the programmer can use the shorter

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

which can be further compacted since "myvec" implements begin/end iterators:

for(auto&x:myvec)

This difference grows as the programmer begins to nest containers, though in such cases s are a good way to decrease the amount of code.

The type denoted by can be different from the type deduced by .

#include<vector>intmain(){conststd::vector<int>v(1);autoa=v[0];// a has type intdecltype(v[0])b=1;// b has type const int&, the return type of// std::vector<int>::operator[](size_type) constautoc=0;// c has type intautod=c;// d has type intdecltype(c)e;// e has type int, the type of the entity named by cdecltype((c))f=c;// f has type int&, because (c) is an lvaluedecltype(0)g;// g has type int, because 0 is an rvalue}

Range-based for loop[edit]

C++11 extends the syntax of the statement to allow for easy iteration over a range of elements:

intmy_array[5]={1,2,3,4,5};// double the value of each element in my_array:for(int&x:my_array){x*=2;}// similar but also using type inference for array elementsfor(auto&x:my_array){x*=2;}

This form of , called the “range-based for”, will iterate over each element in the list. It will work for C-style arrays, initializer lists, and any type that has and functions defined for it that return iterators. All the standard library containers that have begin/end pairs will work with the range-based for statement.

Lambda functions and expressions[edit]

Main article: Anonymous function § C++ (since C++11)

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

[](intx,inty)->int{returnx+y;}

The return type ( in this example) can be omitted as long as all expressions return the same type. A lambda can optionally be a closure.

Alternative function syntax[edit]

Standard C function declaration syntax was perfectly adequate for the feature set of the C language. As C++ evolved from C, it kept the basic syntax and extended it where needed. However, as C++ grew more complex, it exposed several limits, especially regarding template function declarations. For example, in C++03 this is disallowed:

template<classLhs,classRhs>Retadding_func(constLhs&lhs,constRhs&rhs){returnlhs+rhs;}//Ret must be the type of lhs+rhs

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

template<classLhs,classRhs>decltype(lhs+rhs)adding_func(constLhs&lhs,constRhs&rhs){returnlhs+rhs;}//Not valid C++11

This is not valid C++ because and 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<classLhs,classRhs>autoadding_func(constLhs&lhs,constRhs&rhs)->decltype(lhs+rhs){returnlhs+rhs;}

This syntax can be used for more mundane function declarations and definitions:

structSomeStruct{autofunc_name(intx,inty)->int;};autoSomeStruct::func_name(intx,inty)->int{returnx+y;}

Use of the keyword “auto” in this case is only part of the syntax and does not perform automatic type deduction.[14]

Object construction improvement[edit]

In C++03, constructors of a class are not allowed to call other constructors in an initializer list of that class. Each constructor must construct all of its class members itself or call a common member function, as follows:

classSomeType{intnumber;private:voidConstruct(intnew_number){number=new_number;}public:SomeType(intnew_number){Construct(new_number);}SomeType(){Construct(42);}};

Constructors for base classes cannot be directly exposed to derived classes; each derived class must implement constructors even if a base class constructor would be appropriate. Non-constant data members of classes cannot be initialized at the site of the declaration of those members. They can be initialized only in a constructor.

C++11 provides solutions to all of these problems.

C++11 allows constructors to call other peer constructors (termed delegation). This allows constructors to utilize another constructor's behavior with a minimum of added code. Delegation has been used in other languages e.g., Java, Objective-C.

This syntax is as follows:

classSomeType{intnumber;public:SomeType(intnew_number):number(new_number){}SomeType():SomeType(42){}};

Notice that, in this case, the same effect could have been achieved by making a defaulting parameter. The new syntax, however, allows the default value (42) to be expressed in the implementation rather than the interface — a benefit to maintainers of library code since default values for function parameters are “baked in” to call sites, whereas constructor delegation allows the value to be changed without recompilation of the code using the library.

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 delegating 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. Thus, the C++11 compiler will generate code to perform the inheritance and the forwarding of the derived class to the base class. This is an all-or-nothing feature: either all of that base class's constructors are forwarded or none of them are. Also, an inherited constructor will be shadowed if it matches the signature of a constructor of the derived class, and restrictions exist for multiple inheritance: class constructors cannot be inherited from two classes that use constructors with the same signature.

The syntax is as follows:

classBaseClass{public:BaseClass(intvalue);};classDerivedClass:publicBaseClass{public:usingBaseClass::BaseClass;};

For member initialization, C++11 allows this syntax:

classSomeClass{public:SomeClass(){}explicitSomeClass(intnew_value):value(new_value){}private:intvalue=5;};

Any constructor of the class will initialize with 5, if the constructor does not override the initialization with its own. So the above empty constructor will initialize 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 assignment initialization shown above.

Explicit overrides and final[edit]

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

structBase{virtualvoidsome_func(float);};structDerived:Base{virtualvoidsome_func(int);};

Suppose the is intended to replace the base class version. But instead, because it has a different signature, 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.

structBase{virtualvoidsome_func(float);};structDerived:Base{virtualvoidsome_func(int)override;// ill-formed - doesn't override a base class method};

The 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 indicate an error.

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 . For example:

structBase1final{};structDerived1:Base1{};// ill-formed because the class Base1 has been marked final
structBase2{virtualvoidf()final;};structDerived2:Base2{voidf();// ill-formed because the virtual function Base2::f has been marked final};

In this example, the 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 nor are language keywords. They are technically identifiers for declarator attributes:

  • they gain special meaning as attributes only when used in those specific trailing contexts (after all type specifiers, access specifiers, member declarations (for struct, class and enum types) and declarator specifiers, but before initialization or code implementation of each declarator in a comma-separated list of declarators);
  • they do not alter the declared type signature and do not declare or override any new identifier in any scope;
  • the recognized and accepted declarator attributes may be extended in future versions of C++ (some compiler-specific extensions already recognize added declarator attributes, to provide code generation options or optimization hints to the compiler, or to generate added data into the compiled code, intended for debuggers, linkers, and deployment of the compiled code, or to provide added system-specific security attributes, or to enhance reflection abilities at runtime, or to provide added binding information for interoperability with other programming languages and runtime systems; these extensions may take parameters between parentheses after the declarator attribute identifier; for ANSI conformance, these compiler-specific extensions should use the double underscore prefix convention).
  • In any other location, they can be valid identifiers for new declarations (and later use if they are accessible).

Null pointer constant[edit]

For the purposes of this section and this section alone, every occurrence of “” is meant as “a constant expression which evaluates to , which is of type int”. In reality, the constant expression can be of any integral type.

Since the dawn of C in 1972, the constant has had the double role of constant integer and null pointer constant. The ambiguity inherent in the double meaning of was dealt with in C by using the preprocessor macro , which commonly expands to either or . C++ forbids implicit conversion from to other pointer types, thus removing the benefit of casting to . As a consequence, only is allowed as a null pointer constant. This interacts poorly with function overloading:

voidfoo(char*);voidfoo(int);

If is defined as (which is usually the case in C++), the statement will call , 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: . It is of type , 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 . While the original proposal specified that an rvalue of type should not be convertible to , 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, remains a valid null pointer constant.

char*pc=nullptr;// OKint*pi=nullptr;// OKboolb=nullptr;// OK. b is false.inti=nullptr;// errorfoo(nullptr);// calls foo(nullptr_t), not foo(int);/* Note that foo(nullptr_t) will actually call foo(char *) in the example above using an implicit conversion, only if no other functions are overloading with compatible pointer types in scope. If multiple overloadings exist, the resolution will fail as it is ambiguous, unless there is an explicit declaration of foo(nullptr_t). In standard types headers for C++11, the nullptr_t type should be declared as: typedef decltype(nullptr) nullptr_t; but not as: typedef int nullptr_t; // prior versions of C++ which need NULL to be defined as 0 typedef void *nullptr_t; // ANSI C which defines NULL as ((void*)0)*/

Strongly typed enumerations[edit]

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. Further, the underlying integral type is implementation-defined; code that depends on the size of the enumeration is thus non-portable. Lastly, enumeration values are scoped to the enclosing scope. Thus, it is not possible for two separate enumerations in the same scope to have matching member names.

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

enumclassEnumeration{Val1,Val2,Val3=100,Val4// = 101};

This enumeration is type-safe. Enum class values are not implicitly converted to integers. Thus, they cannot be compared to integers either (the expression gives a compile error).

The underlying type of enum classes is always known. The default type is ; this can be overridden to a different integral type as can be seen in this example:

enumclassEnum2:unsignedint{Val1,Val2};

With old-style enumerations the values are placed in the outer scope. With new-style enumerations they are placed within the scope of the enum class name. So in the above example, is undefined, but is defined.

There is also a transitional syntax to allow old-style enumerations to provide explicit scoping, and the definition of the underlying type:

enumEnum3:unsignedlong{Val1=1,Val2};

In this case the enumerator names are defined in the enumeration's scope (), but for backwards compatibility they are also placed in the enclosing scope.

Forward-declaring enums are also possible in C++11. Formerly, enum types could not be forward-declared because the size of the enumeration depends on the definition of its members. As long as the size of the enumeration is specified either implicitly or explicitly, it can be forward-declared:

enumEnum1;// Invalid in C++03 and C++11; the underlying type cannot be determined.enumEnum2:unsignedint;// Valid in C++11, the underlying type is specified explicitly.enumclassEnum3;// Valid in C++11, the underlying type is int.enumclassEnum4:unsignedint;// Valid in C++11.enumEnum2:unsignedshort;// Invalid in C++11, because Enum2 was formerly declared with a different underlying type.

Right angle bracket[edit]

C++03's parser defines “” as the right shift operator or stream extraction 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 around parameter expressions using the “”, “” or “” binary operators:

template<boolTest>classSomeType;std::vector<SomeType<1>2>>x1;// Interpreted as a std::vector of SomeType<true>,// followed by "2 >> x1", which is not valid syntax for a declarator. 1 is true.std::vector<SomeType<(1>2)>>x1;// Interpreted as std::vector of SomeType<false>,// followed by the declarator "x1", which is valid C++11 syntax. (1>2) is false.

Explicit conversion operators[edit]

C++98 added the keyword as a modifier on constructors to prevent single-argument constructors from being used as implicit type conversion operators. However, this does nothing for actual conversion operators. For example, a smart pointer class may have an to allow it to act more like a primitive pointer: if it includes this conversion, it can be tested with (which would be true if the pointer was non-null and false otherwise). However, this allows other, unintended conversions as well. Because C++ is defined as an arithmetic type, it can be implicitly converted to integral or even floating-point types, which allows for mathematical operations that are not intended by the user.

In C++11, the keyword can now be applied to conversion operators. As with constructors, it prevents using those conversion functions in implicit conversions. However, language contexts that specifically need a boolean value (the conditions of if-statements and loops, and operands to the logical operators) count as explicit conversions and can thus use a bool conversion operator.

For example, this feature solves cleanly the safe bool issue.

Template aliases[edit]

In C++03, it is possible to define a typedef only as a synonym for another type, including a synonym for a template specialization with all actual template arguments specified. It is not possible to create a typedef template. For example:

template<typenameFirst,typenameSecond,intThird>classSomeType;template<typenameSecond>typedefSomeType<OtherType,Second,5>TypedefName;// Invalid in C++03

This will not compile.

C++11 adds this ability with this syntax:

template<typenameFirst,typenameSecond,intThird>classSomeType;template<typenameSecond>usingTypedefName=SomeType<OtherType,Second,5>;

The syntax can be also used as type aliasing in C++11:

typedefvoid(*FunctionType)(double);// Old styleusingFunctionType=void(*)(double);// New introduced syntax

Unrestricted unions[edit]

In C++03, there are restrictions on what types of objects can be members of a . For example, unions cannot contain any objects that define a non-trivial constructor or destructor. C++11 lifts some of these restrictions.[3]

If a member has a non trivial special member function, the compiler will not generate the equivalent member function for the and it must be manually defined.

This is a simple example of a union permitted in C++11:

#include<new> // Needed for placement 'new'.structPoint{Point(){}Point(intx,inty):x_(x),y_(y){}intx_,y_;};unionU{intz;doublew;Pointp;// Invalid in C++03; valid in C++11.U(){}// Due to the Point member, a constructor definition is now needed.U(constPoint&pt):p(pt){}// Construct Point object using initializer list.U&operator=(constPoint&pt){new(&p)Point(pt);return*this;}// Assign Point object using placement 'new'.};

The changes will not break any existing code since they only relax current rules.

Core language functionality improvements[edit]

These features allow the language to do things that were formerly impossible, exceedingly verbose, or needed non-portable libraries.

Variadic templates[edit]

Main article: Variadic template

In C++11, templates can take variable numbers of template parameters. This also allows the definition of type-safe variadic functions.

New string literals[edit]

C++03 offers two kinds of string literals. The first kind, contained within double quotes, produces a null-terminated array of type . The second kind, defined as , produces a null-terminated array of type , where is a wide-character of undefined size and semantics. Neither literal type offers support for string literals with UTF-8, UTF-16, or any other kind of Unicode

Overloaded assignment operator for class template objects

I designed a class template to create unique arrays. I was able to successfully input data to and output data from my array objects, irrespective of the datatype. However, I can't for the life of me fathom why my overloaded assignment operator worked perfectly well only for integer datatype and not for double/string datatypes.


Here is the class definition:




And here is the definition of the overloaded assignment operator:




And here is my main function that tests the operations on objects of the class:



The problem I'm having starts from where the assignment operator is being tested: for double and string datatypes, the upper input/output section works fine, but the assignment section freezes the display until the program execution is manually terminated!!

Any helpful insights would be highly appreciated. Please feel free to ask or request for clarifying info about the code. Thanks as I eagerly await your responses.
What if lower bound is 9 and upper bound is 100? You will create an array of size 1, but will try to access 99th element.
Also problem with negative elements. Remember: arratPtr[i] will not use overloaded operator[].
If it works for ints, I think you have some problems with operator[] too. Show it.
Thanks MiiNiPaa for your prompt reply. Let me try to respond:

You wrote: "What if lower bound is 9 and upper bound is 100? You will create an array of size 1, but will try to access 99th element."
Did you mean to write 10 and not 100? 'Cause that's the only way the array size would result in 1.

Also you wrote: "Also problem with negative elements." Did you mean negative elements of the array OR negative parameters at object declaration? Anyways, the index of arrayPtr (= i) can never be negative, given some object declaration constraint (e.g. upperBound>lowerBound) and the way I wrote the constructor.

The constructor is definitely not the problem; like I implied in my earlier post, the objects of the class were successfully created (for integer, double, and string datatypes); it's the assignment operation that's failing me, I'm guessing. Here are my constructor and the overloaded operator[] you asked for:






By the way, I'm jealous of the way you captured the exact fonts/color of my program segment. Yours even had line numbers! So cool! How do I go about doing that on here; I'm fairly new to the forum. Thanks.


There is code tags button. It looks like <>.

Did you mean to write 10 and not 100?
I meant 99 :)

In your constructor: if you pass (-10, 0) as parameters, it will create array of size 10 with valid indexes [0,9]
But if you call yoir object as x[-8] it will chech that it is between lower and upper bound (which is true) and will try to do , which is dangerous and can lead to crash.
You probably intended to normalize your range and access underlying array as
What is the problem with the copy assignment operator? I would decalre it without qualifier const in the return type




As for me I would make arrayUpperBound acceptable to specify as an index.
I wouldn't use copy, I'd use move instead such that if the object has a copy constructor for a rvalue reference then you will be saying time instead of allocating extra memory in the copy.

I wouldn't use copy, I'd use move instead


Logically that wouldn't make sense. This is copy assignment, not move assignment. The elements to be moved are const and thus cannot be "moved" as doing so requires the source elements to be modified.


[edit: typo'd]

@MiiniPaa: I see your point about the dangers of problematic "extreme" parameters during object declaration. However, the point still remains that I did not use those extreme parameter cases in my first post above that worked for integer datatypes but failed for double/string datatypes. I have already designed a more versatile constructor to take care of those extreme parameters at object declarations. It just boggles the mind that the same set of parameters that worked for integers would not work for double/string datatypes.

@vlad from moscow: Let's assume the "const" in the return type were the problem, how come this did not affect the integer datatype runs I did, all of whose assignment operations were successfully implemented??

@xerzi: Well, the "Law of the Big Three" stipulates inclusion of the copy constructor in a class with pointer data members.

@cire: I think I agree with your objection to xerzi's post.


Still looking forward to any helpful insights. Thank you all.


I did not know what is your problem with the copy assignment operator because you did not say nothing about it.
@vlad from moscow:
I did not know what is your problem with the copy assignment operator because you did not say nothing about it.

If you examine my first post in which I show function main, you would see four assignment statements in lines 40, 45, 50 & 55. These are the lines that are giving me a headache. Like I said in my first post, these assignment statements are successfully achieved when the objects are of integer datatype. However, program execution halts if the objects are of double/string datatypes. That's why it makes sense to think that my overloaded assignment statement is the problem. But from a theoretical standpoint, I can't see where my overloaded assignment operator function is wrong.


@cire: I'll try to go over that website you suggested.

Thanks all! The search for a reason for this datatype-based execution anomaly continues.
I would guess that, since every function you've shown so far has handled indexing your array incorrectly (ie: not adjusting the index to be zero-based before using it to access the array), by the time you get to the later tests you've been steadily trashing memory and the results of that finally show up.

@cire:
You wrote:
I would guess that, since every function you've shown so far has handled indexing your array incorrectly (ie: not adjusting the index to be zero-based before using it to access the array), ...


Well that's the point of the task I embarked upon: to create non-conventional (not necessarily zero-based) arrays that are strictly based on the definition of the class to which they belong. I beg to differ that the indexing is being handled incorrectly because my overloaded array index operator function(definition shown in an earlier post) has already taken care of the non-zero-based feature of the objects of the class.
Read my posts again.
If you create it will create array with one element.
If you do it will pass your checks, but will access 100th one which is overflow

If you create it will create array with ten elements.
If you do it will pass your checks, but will access -8th element, which is invalid for arrays.

Look what your function doing in these cases step by step and you will probably understand that yourself
@MiiNiPaa & @cire:

I think I'm starting to see your points about the array indexing angle to my problem. For some reason, I have apparently and erroneously overlooked the fact that within the function definition of the operator I'm trying to overload, the primary ANSI C++ definition of that same operator is still preserved.

MiiNiPaa's examples sort of illustrate this: in main function, given the nature of my class, it makes sense to have y[-8] (i.e. trying to access an array component of object y); however, within the overloaded operator function's definition for [], this array component reference is gibberish!!

I'll go and explore this dimension to the problem and let you guys know if it resolves it. In the meantime, thanks.
MiiNiPaa wrote:
You probably intended to normalize your range and access underlying array as
@MiiNiPaa:

Oh yeah! Although I had already come up with arrayPtr[index + (-1*arrayLowerBound)], essentially the same as yours. It's funny how even though I read all your prior posts, the epiphany I had on the indexing pitfall of my code did not occur until my last post. I observed you caught this pretty early on!

After making the necessary adjustments, I observed a marginal improvement in program behavior; however, I now see some strange, random, large numbers in the assignment section that I did not input in the first place! This aberrant behavior even for integer datatypes that I thought were in the clear before. Of course, the object input/output section for all datatypes still works fine; the assignment section of the code is where things go awry.

I have included a sample program output here for your observation:






Any insights?

If that wasn't changed, you got same problem here. Either use your array subscript operator to handle this, or corrext indexes manually.
Like I said, I already made all the adjustments related to the array indexing throughout my class' member functions.

0 thoughts on “Overload Assignment Operator C++ Template Typedef

Leave a Reply

Your email address will not be published. Required fields are marked *