1. 서로 다른 클래스 상에서는 같은 이름으로 enum type이 정의되더라도 독립적으로 사용 가능함

 

class A
{
    public:

    enum Color
    {
        red = 1,
        blue = 2,
        green = 3
    };
    
    void funcA()
    {
        cout<< Color::red <<" "<< Color::blue <<" "<<Color::green <<endl;
    }
};

class B
{
    public:

    enum Color
    {
        red = 11,
        blue = 22,
        green = 33
    };
    
    void funcB()
    {
        cout<< Color::red <<" "<< Color::blue <<" "<<Color::green <<endl;
    }
};

int main()
{
    A a;
    B b;
    
    a.funcA(); // 1,2,3
    b.funcB(); // 11,22,33
    

    return 0;
}

 

2. 그러나 같은 클래스 내에서는 enum 타입이 다르더라도, 동일한 이름의 enum 변수가 존재할 경우 compile error

 

class A
{
    public:

    enum Color
    {
        red = 1,
        blue = 2,
        green = 3
    };

    enum AdvancdedColor
    {
        red = 100,
        blue = 200,
        green = 300
    };
    
    void funcA()
    {
        cout<< Color::red <<" "<< Color::blue <<" "<<Color::green <<endl;
    }
};

int main()
{
    A a;
    a.funcA();  // compile error
    
    return 0;
}

 

컴파일러에서는 enum을 다음과 같이 처리함.

즉, (default type인) uint 형으로 casting 하게 되는데, 이름이 중복되기 때문에 컴파일 에러를 발생시키는 것임.

 

class A
{
  
  public: 
  enum Color
  {
    red = static_cast<unsigned int>(1), 
    blue = static_cast<unsigned int>(2), 
    green = static_cast<unsigned int>(3)
  };
  
  enum AdvancdedColor
  {
    red = static_cast<unsigned int>(100), 
    blue = static_cast<unsigned int>(200), 
    green = static_cast<unsigned int>(300)
  };
  
};

 

3. enum class 는 2번과 같은 상황에서 enum 타입이 다르다면 동일한 변수를 사용할 수 있게끔 해줌

    (enum class 내에 있는 값들은 서로 독립된 값으로 switch 문이나 if 에서 구분지을 때는 바로 사용 가능하나,
     값을 print 하거나 비교하기위해서는 casting 해줘야 함; 아래 예시의 경우에는 int 형으로 type deduction 됨)

 

class A
{
    public:

    enum class Color
    {
        red = 1,
        blue = 2,
        green = 3
    };

    enum class AdvancdedColor
    {
        red = 100,
        blue = 200,
        green = 300
    };
    
    void funcA()
    {
        cout<< static_cast<int>(Color::red) <<" "<< static_cast<int>(AdvancdedColor::red) <<endl;
    }
};

int main()
{
    A a;
    a.funcA();
    

    return 0;
}

 

컴파일러가 enum class 를 인식한 결과는 아래와 같음

 


  enum class Color : int
  {
    red = 1, 
    blue = 2, 
    green = 3
  };
  
  enum class AdvancdedColor : int
  {
    ared = 100, 
    ablue = 200, 
    agreen = 300
  };

 

 

 

int num[7] = { 45,6,3,32,5,53,12 }

sort(nums, nums+7, [ ] (int a , int b) {return a > b ; } );

Anonymous function

It allows a function to be defined at the point where it’s needed in another expression

A lambda expression can have more power than an ordinary function by having access to variables from the enclosing scope

lambda template

[] :  lambda introducer which denotes the start of the lambda expression

() : parameter list which is similar to the () operator of a normal function

captures

Params : the list of parameters as in named functions

specs (optional)
-specifiers : (mutable (C++11), constexpr(C++17), consteval(C++20), static(C++23) )
-trailing-return-type : -> ret, where ret specifies the return type

body : function body


Closure type (unnamed nonunion class type)

“The distinction between a lambda and the corresponding closure is precisely equivalent

to the distinction between a class and an instance of the class <effective modern c++>”

 

sample code 1

int num[7] = { 45,6,3,32,5,53,12}

sort(nums, nums+7, [ ] (int a , int b) {return a > b ; } );

sample code 2

class ClosureType{
   public:
       bool operator( )(int a , int b) const {
                  return a > b ;
        }
};


sort(nums, nums+7,  ClosureType() );

 

sample code 3

int main()
{
   [ ] (int a , int b) { return a > b; } (12, 24) ;
   auto l = [ ] (int a , int b) { return a > b; } ;
   cout << l (55,33) <<endl;
}

Type of lambda

The type of the lambda-expression (which is also the type of the closure object) is a unique

 

auto l = [ ](int a, int b) { return a * b } ;

auto l2 = [ ](int a, int b) { return a * b } ;

cout<<typeid(l).name()<<endl;

cout<<typeid(l2).name()<<endl;

 


Inline replacement

 

sample code 4

auto lambda = [ ](int a, int b) { return a * b } ;                   //  inline replacement - O
int (*fp)(int, int) = [ ](int a, int b) { return a * b };            //  inline replacement - X
function<int(int, int) > func = [ ](int a , int b) { return a* b; }; //  inline replacement - X

lambda = [ ](int a, int b) { return a + b } ;  //error
fp = [ ](int a, int b) { return a + b };
func =  [ ](int a , int b) { return a - b; };

Passing lambda function as arguments

1) function pointer or std::function object

 

sample code 5

typedef int (*fp)(int, int);
void foo(fp f)
{
    f(12, 24);
}

int main()
{
    foo( [ ] (int a , int b) { return a * b ; } );   
    foo( [ ] (int a , int b) { return a * b ; } );
}

 

2) template declaration

 

sample code 6

template<typename T>
void foo(T f)
{
    f(12, 24);
}

int main()
{
    foo( [ ] (int a , int b) { return a * b ; } );   
    foo( [ ] (int a , int b) { return a * b ; } );
}

Return type

The compiler can implicitly deduce the return type of the lambda expression based on the return statement

But for multiple return statements of different types, we have to explicitly define the type valuation

 

sample code 7

auto  f2 = [ ](int a , int b) { 
                       if(a% 2) {
                             return a;
                        }else{
                             return b;
                        }  }

 

sample code 8

auto  f2 = [ ] -> double (int a , double b) { 
                       if(a% 2) {
                             return a;
                        }else{
                             return b;
                        }  }

Capture

By default, lambda functions cannot access variables of the enclosing function

In order to access those variables, we use the capture clause.

 

Capture by value

- Basic expression:  [data] (..) { … }

- The actual value is copied when the lambda is created.

- we can only read the variable inside the lambda body but cannot modify it.

- [=] says all the variables of the enclosing function are captured by value.

 

Capture by reference

- Basic expression:  [&data] (..) { … }

- The lambda has access to the variable address.

- we can read the variable as well as modify it inside the lambda body.

- [&] indicates that all the variables are captured by reference

 

sample code 9

int gVal = 100;   // global variable
int main() 
{ 
   int val1 = 20; 
   int val2 = 30; 
   auto f1 = [ ](int a) { gVal = 10; return a + gVal; }; 
   auto f2 = [ ](int a) { return a + val1; };    // error
   auto f3 = [val1](int a) { return a + val1; }; 
   auto f4 = [val1, val2](int a) { return a + val1 + val2; }; 
   auto f5 = [val1](int a) { val1 = 2; return a + val1; }; // error  
   auto f6 = [val1](int a) mutable { val1 = 2; return a + val1; };  
}

 

sample code 10

class ClosureType{
   public:
       ClosureType(int a): val1(a)
       bool operator( )(int a) const {
                  val1 = 2;
                  return a + val1 ;
        }
    private:
        int val1;
};

 

sample code 11

int main( ) 
{ 
   int val1 = 20; 
   int val2 = 30; 
    auto f = [val1, val2]( ) { return val1 + val2; };

    auto f2 = [ ] () { return true; };

    cout<< sizeof(f) << “,” <<sizeof(f2) << endl; 
}

 

sample code 12

class ClosureType{
  public:
       ClosureType(int a, int b): val1(a), val2(b) { }
       bool operator( )( ) const {
                  return val1 + val2 ;
        }
 private:
       int val1;
       int val2;
};

 

sample code 13

int main()
{   
    int val1 = 0; 
    int val2 = 10;
    int val3 = 100; 

    auto f1 = [val1]( ) { };
    auto f2 = [&val2 ] ( ) { };
    auto f3 = [val1, &val2 ] ( ) { };
    auto f4 = [=] () { };
    auto f5 = [&] () { };
    auto f6 = [=, &val1] () { };   
    auto f7 = [&, val1] () { };     
    auto f8 = [=, val1] () { };
    
    auto f9 = [ a = val1, val2 = val2, val3] ( ) { } ;
    auto f10 = [  val1, b = val2, &r = val3] ( ) { } ;

	std::string s  = “hello world”;
	auto f11 = [ d = move(s) ] () {cout<<d<<endl; } ;
	cout<< s << endl; 
	f11();

}

unique_ptr

+ Recent posts