Combining the new features of C++11 to resolve enumerations and Federated _c languages in C + +

Source: Internet
Author: User
Tags anonymous constant

Enumeration
enumerations are user-defined types that contain a set of named integer constants called enumerators.
Grammar

unscoped enum:
enum [identifier] [: Type]

{enum-list}; 

scoped enum:
enum [class|struct] 
[identifier] [: Type] 
{enum-list};
Forward Declaration of Enumerations (C++11):
enum a:int;//non-scoped enum must have type specified
enum CL Ass B; scoped enum defaults to int
enum class C:short;

Parameters
Identifier
Specifies the name of the type given to the enumeration.
Type
The underlying type of the enumerator; all enumerators have the same underlying type. may be any integral type.
Enum-list
A comma-delimited list of enumerators in the enumeration. Each enumerator or variable name in the range must be unique. However, values can be duplicated. In an undefined range of enumerations, the scope is a perimeter; in a range-scoped enumeration, the scope is the enum-list itself.
Class
You can use this keyword in the declaration to specify an enumeration scope and must provide identifier. You can also use the struct keyword instead of class because they are semantically equivalent in this context.
Note
Enumeration provides a context to describe a series of values represented by named constants, which are also called enumerators. In the original C and C + + enumeration types, the unqualified enumerator is visible in the entire scope of the Declaration enumeration. In a scoped enumeration, the enumerator name must be qualified by the enumeration type name. The following example shows the basic differences between two enumerations:

Namespace cardgame_scoped
{
  enum class Suit {Diamonds, Hearts, Clubs, spades};

  void Playcard (Suit Suit)
  {
    if (Suit = = suit::clubs)//enumerator must is qualified by enum type
    {/*...*/}
   }
}

namespace cardgame_nonscoped
{
  enum Suit {diamonds, Hearts, Clubs, spades};

  void Playcard (Suit Suit)
  {
    if (Suit = = clubs)//enumerator is visible without qualification
    {/*...*/
   
    }
  }
}


   

An integer value is assigned to each name in the enumeration, which corresponds to the order in the enumeration. By default, assign 0 to the first value, assign 1 to the next value, and so on, but you can explicitly set the value of the enumerator as follows:

Enum Suit {diamonds = 1, hearts, Clubs, spades};

Assigns a value of 1 to the enumerator diamonds. The value that the subsequent enumerator receives is based on the value of the previous enumerator, if no explicit assignment is added. In the previous example, Hearts will have a value of 2,clubs with a value of 3, and so on.
Each enumerator is treated as a constant and must have a unique name in the scope of the definition of the enum (for a case-insensitive enumeration) or in the enumeration itself (for scoped enumerations). The values specified for these names do not have to be unique. For example, if an Suit enumeration is declared as follows:

Enum Suit {diamonds = 5, hearts, clubs = 4, spades};

The values for diamonds, hearts, clubs, and spades are 5, 6, 4, and 5, respectively. Note that 5 has been used several times, although this does not meet expectations, but is allowed. These rules are the same for scoped enumerations.
Cast rule
An enumerated constant with an undefined range can be implicitly converted to an int, but an int cannot be implicitly converted to an enumeration value. The following example shows what might happen if you try to assign a value that is not a Suit to hand:

int account_num = 135692;
Suit hand;
hand = Account_num; Error C2440: ' = ': cannot convert from ' int ' to ' Suit '

A cast is required when converting an int to a range-or-insensitive enumerator. However, you can promote a range-scoped enumerator to an integer value without casting.

int account_num = hearts; OK if Hearts is in a unscoped enum

Using implicit conversions in this way can cause unexpected side effects. To help eliminate programming errors associated with scoping enumerations, the range-scoped enumeration value must be a strongly typed value. The scoped enumerator must be qualified by the enumeration type name (identifier) and cannot be implicitly converted, as shown in the following example:

Namespace Scopedenumconversions
{
  enum class Suit {Diamonds, Hearts, Clubs, spades};

  void Attemptconversions ()
  {
    Suit hand; 
    hand = clubs; Error C2065: ' Clubs ': undeclared identifier
    hand = Suit::clubs,//correct.
    int account_num = 135692;
    hand = Account_num; Error C2440: ' = ': cannot convert from ' int ' to ' Suit '
    hand = static_cast<suit> (account_num);//OK, but pro bably a bug!!!

    Account_num = Suit::hearts; Error C2440: ' = ': cannot convert from ' Suit ' to ' int '
    account_num = static_cast<int> (suit::hearts);//Ok
   }

Note that hand = Account_num; The row will still cause an error to occur for an undefined range enumeration, as shown earlier. It can be used with an explicit cast. However, with a scoping enumeration, the Next Statement account_num = Suit::hearts is no longer allowed without an explicit cast; Attempt to convert in.

Joint

A union is a user-defined type in which all members share the same memory location. This means that at any given time, the Union cannot contain multiple objects from its member list. This also means that no matter how many Members the union has, it always uses only the memory sufficient to store the largest member.
With a large number of objects and/or limited memory, unions can be used to conserve memory. However, you need to be extra careful to use them correctly because you are responsible for ensuring that the last member of the write is always accessible. If any member type has a less common constructor, you must write additional code to explicitly construct and destroy the member. Before using unions, you should consider whether you can use base classes and derived classes to better represent the problems that you are trying to resolve.

Union [name] {member-list};

Parameters
Name
The type name provided for the Union.
Member-list
The members that the Union can contain. See "Remarks".
Note
Declaration Union
Use the Union keyword to start a federated declaration and include a list of members with curly braces:

Declaring_a_union.cpp
Union recordtype  //Declare A simple union type
{
  char  ch;
  int  i;
  Long  l;
  float F;
  Double D;
  int *int_ptr;
}; 
int main ()
{
  recordtype t;
  T.I = 5; T holds an int
  T.F = 7.25//t now holds a float 
}

Use federated
In the preceding example, any code that accesses the Union needs to know the member who saved the data. The most common solution to this problem is to put the union and other enumeration members, which indicate the type of data currently stored in the Union, into a structure. This is known as a discriminated union, and the following example demonstrates the basic pattern.

#include "stdafx.h" #include <queue> using namespace std;

Enum class Weatherdatatype {temperature, wind};
  struct TempData {int stationid;
  time_t time;
  Double current;
  Double Max;
Double min;

};
  struct Winddata {int stationid;
  time_t time;
  int speed;
Short direction;

};
  struct Input {weatherdatatype type;
    Union {TempData Temp;
  Winddata Wind;
};

}; Functions that are specific to data types void Process_temp (TempData t) {} void Process_wind (Winddata w) {}//contain
Er for all the data records queue<input> inputs;


void Initialize ();
  int main (int argc, char* argv[]) {Initialize ();
    while (!inputs.empty ()) {Input i = Inputs.front ();
      Switch (i.type) {case weatherdatatype::temperature:process_temp (i.temp);
    Break
      Case Weatherdatatype::wind:process_wind (I.wind);
    Break
    Default:break;

  } inputs.pop ();
return 0; } void Initialize () {Input-I, SECond
  First.type = weatherdatatype::temperature;
  First.temp = {101, 1418855664, 91.8, 108.5, 67.2};

  Inputs.push (a);
  Second.type = Weatherdatatype::wind;
  Second.wind = {204,1418859354, 14, 27};
Inputs.push (second);

 }


In the previous example, note that the Union in the INPUT structure does not have a name. This is an anonymous union that can access its members as if they were direct members of the structure. For more information about anonymous unions, see the following section.
Of course, the problem shown in the previous example can also be resolved by using a class derived from a common base class and branching the code based on the Run-time type of each object in the container. This can generate code that is easier to maintain and understand, but may also be slower than using syndication. In addition, unions can store completely unrelated types and dynamically change the type of stored values without changing the type of the union variable itself. Therefore, you can create myuniontype heterogeneous arrays whose elements store different types of different values.
Note that the INPUT structure in the previous example may be easily misused. The user is solely responsible for using the discriminator correctly to access the member who holds the data. You can prevent misuse by making the Union private and providing special access functions (as shown in the following example).
Unrestricted Union (C++11)
In C++03 and earlier versions, a union can contain non-static data members with class types, provided that the type does not have a user-supplied constructor, destructor, or assignment operator. In c++11, these restrictions are eliminated. If you include such a member in the union, the compiler automatically marks any special member functions that are not supplied by the user as deleted. If the union is an anonymous union in a class or struct, the class or struct is not a user-supplied special member function that is marked as deleted. The following example shows how to handle a member of a union that has a member that requires this special handling:

For myvariant #include <crtdbg.h> #include <new> #include <utility>//For sample objects and OUTPU

T #include <string> #include <vector> #include <iostream> using namespace std;
  struct a {a () = default;
  A (int i, const string& str): num (i), name (str) {} int num;
  String name;

//...
};
  struct B {b () = default;
  B (int i, const string& str): num (i), name (str) {} int num;
  String name;
  Vector<int> VEC;

// ...
};

Enum class Kind {None, A, B, Integer};
  #pragma warning (push) #pragma warning (disable:4624) class Myvariant {public:myvariant (): Kind_ (Kind::none) {
    Myvariant (Kind Kind): Kind_ (Kind) {switch (kind_) {case kind::none:break;
      Case Kind::a:new (&a_) A ();
    Break
      Case Kind::b:new (&b_) B ();
    Break
      Case kind::integer:i_ = 0;
    Break
      Default: _assert (FALSE);
    Break }} ~myVariant () {switch (kind_) {case kind::none:break;
      Case Kind::a:a_.~a ();
    Break
      Case Kind::b:b_.~b ();
    Break
    Case Kind::integer:break;
      Default: _assert (FALSE);
    Break
  } kind_ = Kind::none;
      Myvariant (const myvariant& Other): Kind_ (other.kind_) {switch (kind_) {case Kind::none:
    Break
      Case Kind::a:new (&a_) A (Other.a_);
    Break
      Case Kind::b:new (&b_) B (other.b_);
    Break
      Case kind::integer:i_ = other.i_;
    Break
      Default: _assert (FALSE);
    Break
      } myvariant (myvariant&& Other): Kind_ (other.kind_) {switch (kind_) {case Kind::none:
    Break
      Case Kind::a:new (&a_) A (Move (Other.a_));
    Break
      Case Kind::b:new (&b_) B (Move (other.b_));
    Break
      Case kind::integer:i_ = other.i_;
    Break
    Default  _assert (FALSE);
    Break
  } other.kind_ = Kind::none; 
      } myvariant& operator= (const myvariant& Other) {if (&other!= this) {switch (other.kind_)
        {case kind::none:this->~myvariant ();
      Break
        Case KIND::A: *this = Other.a_;
      Break
        Case KIND::B: *this = other.b_;
      Break
        Case Kind::integer: *this = other.i_;
      Break
        Default: _assert (FALSE);
      Break
  } return *this;
    } myvariant& operator= (myvariant&&) {_assert (this!= &other);
      Switch (other.kind_) {case kind::none:this->~myvariant ();
    Break
      Case KIND::A: *this = Move (Other.a_);
    Break
      Case KIND::B: *this = Move (other.b_);
    Break
      Case Kind::integer: *this = other.i_;
    Break
      Default: _assert (FALSE);
    Break } other.kind_ = Kind::none;
    return *this; } myvariant (const a& a): Kind_ (KIND::A), A_ (a) {} myvariant (a&& a): Kind_ (KIND::A), A_ (Mo ve (a)) {} myvariant& operator= (const a& a) {if (Kind_!= kind::a) {this->~myvariant ()
      ;
    New (This) myvariant (a);
    else {a_ = A;
  return *this;
      } myvariant& operator= (a&& A) {if (Kind_!= kind::a) {this->~myvariant ();
    New (This) myvariant (move (a));
    else {A_ = Move (a);
  return *this; } myvariant (const b& B): Kind_ (KIND::B), b_ (b) {} myvariant (b&& b): Kind_ (KIND::B), B_ (Mo ve (b)) {} myvariant& operator= (const b& b) {if (Kind_!= kind::b) {this->~myvariant ()
      ;
    New (this) myvariant (b);
    else {b_ = b;
  return *this; } myvariant& operator= (b&& B) {if (Kind_!= kind::b) {thIs->~myvariant ();
    New (This) myvariant (move (b));
    else {b_ = move (b);
  return *this; myvariant (int i): Kind_ (Kind::integer), i_ (i) {} myvariant& operator= (int i) {if (Kind_!= Ki
      Nd::integer) {this->~myvariant ();
    New (This) myvariant (i);
    else {i_ = i;
  return *this;
  } Kind Getkind () const {return kind_;
    } a& Geta () {_assert (Kind_ = = kind::a);
  return a_;
    Const a& Geta () const {_assert (Kind_ = = kind::a);
  return a_;
    } b& Getb () {_assert (Kind_ = = kind::b);
  return b_;
    Const b& GETB () const {_assert (Kind_ = = kind::b);
  return b_;
    } int& Getinteger () {_assert (Kind_ = = Kind::integer);
  return i_;
    Const int& Getinteger () const {_assert (Kind_ = = Kind::integer);
  return i_;
  } Private:kind Kind_;
    Union {A A_;
    B b_;
  int i_; };
};
  #pragma warning (pop) int main () {A A (1, "Hello from a");

  b b (2, "Hello from B");

  Myvariant mv_1 = A;
  cout << "mv_1 = A:" << Mv_1.geta (). Name << Endl;
  Mv_1 = b;
  cout << "mv_1 = B:" << Mv_1.getb (). Name << Endl;
  Mv_1 = A (3, "Hello again from A");
  cout << R "AAA" (Mv_1 = A (3, "Hello Again from"):) AAA "<< Mv_1.geta (). Name << Endl;
  Mv_1 = 42;

  cout << "mv_1 =:" << mv_1.getinteger () << Endl;

  B.vec = {10,20,30,40,50};
  Mv_1 = Move (b);

  cout << "after move, mv_1 = B:vec.size =" << Mv_1.getb () vec.size () << Endl;
  cout << Endl << "Press a letter" << Endl;
  char c;
CIN >> C;


#include <queue> #include <iostream> using namespace std;

Enum class Weatherdatatype {temperature, wind}; struct TempData {tempdata (): Stationid (""), Time (0), current (0), maxtemp (0), mintemp (0) {} tempdata (string ID, time_ T T, double cur, Double max, double min): Stationid (ID), time (t), current (cur), maxtemp (max), mintemp (0) {} string Stationid;
  time_t time = 0;
  Double current;
  Double maxtemp;
Double mintemp;

};
  struct Winddata {int stationid;
  time_t time;
  int speed;
Short direction;

};
    struct Input {input () {} input (const input&) {} ~input () {if (type = = Weatherdatatype::temperature) {Temp.
    Stationid.~string ();
  } weatherdatatype type;

    void Settemp (const tempdata& td) {type = Weatherdatatype::temperature;
    Must use placement new because of string member!
  New (&temp) TempData (TD);
    } tempdata Gettemp () {if (type = = weatherdatatype::temperature) return temp;
  else throw logic_error ("Can ' t return TempData when Input holds a winddata");  } void Setwind (Winddata wd) {//explicitly delete struct member that has a//non-trivial constructor if
    (type = = Weatherdatatype::temperature)
  {    Temp.
    Stationid.~string (); Wind = WD;
  Placement new not required.
    } winddata Getwind () {if (type = = Weatherdatatype::wind) {return wind;
  else throw logic_error ("Can ' t return Winddata when Input holds a tempdata");
    } private:union {TempData temp;
  Winddata Wind;
};

 };

Unions cannot store references. The Union does not support inheritance, so the Union itself cannot be used as a base class, inherits from another class, or has virtual functions.
Initializing Union
You can declare and initialize the union in the same statement by specifying an expression that is contained in parentheses. Evaluates the expression and assigns it to the first field of the Union.

#include <iostream>
using namespace std;

Union Numerictype
{
  short    ivalue;
  Long    LValue; 
  Double   dvalue; 
};

int main ()
{
  union Numerictype Values = {};  Ivalue =
  cout << values.ivalue << Endl;
  Values.dvalue = 3.1416;
  cout << values.dvalue) << Endl;
}
/* Output
 :
 3.141600
*

The Numerictype are arranged in memory (conceptually), as shown in the following illustration.

Anonymous Union
Anonymous union is declared without class-name or declarator-list union.
Union {Member-list}
Names declared in an anonymous union can be used directly, just like a non-member variable. Therefore, the names declared in the anonymous Union must be unique within the perimeter scope.
In addition to the restrictions listed in federated member data, anonymous unions are subject to additional restrictions:
If you declare a union within a file or namespace scope, you must also declare them as "static."
They can have only public members; private members and protected members in an anonymous union generate an error.
They cannot have function members.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.