프로그래밍/C++

[C++] range for / if init / if constexpr

갓똥 2019. 10. 18. 00:31
728x90
반응형

1. range for

#include <iostream>

int main() {
    int x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    for(int n : x) { // x에서 하나를 꺼내서 n에다 담아주세요.
        std::cout << n << ", "; // 배열의 크기가 달라져도 바로 대응 가능
    }
    
    /* 기존 C++에서의 반복문
    for(int i=0; i<10; i++) {
        std::cout << x[i] << ", ";
    }
    */
}

    - C++11부터 지원되는 새로운 모양의 반복문

    - Java/C#의 foreach와 유사한 구문

    - 배열 뿐 아니라 STL의 다양한 컨테이너(list, vector, set 등)를 사용 가능

    - auto와 같이 사용되는 경우가 많이 있다.

    - 사용자가 만든 list도 사용 가능

 


2. if init

int num() { return -1; }

int main() {
    /*
    int tet = num();
    
    if(tet == -1) {
        // ...
    }
    */
    // 위와 아래는 같은 기능
    if(int tet = num(); tet == -1) {
        // ...
    }
    
    /*
    int n = num();
    switch(n) {
        case 10:
            break;
        case 20:
            break;
    }
    */
    // 위와 아래는 같은 기능
    switch(int n = num(); n) {
        case 10:
            break;
        case 20:
            break;
    }
}

    - 조건문(if, switch)을 만들 때 초기화 구문을 추가 할 수 있다.

    - C++17부터 지원하는 문법

 


3. if constexpr

int main() {
    int n = 0;
    
    if(n == 0) {
        // ...
    }
    
    if constexpr(n == 0) { // error - 컴파일시간에 n을 결정 불가
        // ...
    }
    
    if constexpr (sizeof(n) == 0) { // ok - sizeof함수는 컴파일 시간에 검사하므로 ok
        // ...
    }
}

    - if

        => 실행 시간에 조건식을 조사

    - if constexpr

        => 컴파일 시간에 조건식을 조사

        => 조건식은 반드시 컴파일 시간에 값을 결정할 수 있어야 한다.

        => static if라고도 불리는 문법

    - C++ 17부터 지원하는 문법

    - 템플릿을 만들 때 주로 사용

 

template<typename T>
void num(T a) {
    *a = 0;
}

int main() {
    int n = 0;
    
    num(&n); // T : int* - 역참조로 0을 집어넣는것으로 문제 x.   ok
    num(n);  // T : int  - int에다 역참조로 값을 넣을 수는 없다. error
}

    - 위 코드는 num(n); 에서 n이 int타입으로 num함수 내에서 역참조가 되는데 값을 넣을 수 없으므로 error가 난다.

template<typename T>
void num(T a) {
    if(0)
        *a = 0;
}

int main() {
    int n = 0;
    
    num(&n); 
    num(n);  
}

    - num함수 내에 if(0)을 추가 했다. 생각해보면 if(0)은 항상 false이므로 *a = 0;이 절대 실행 될리가 없다.

    - 그렇다면 이건 컴파일해보면 에러가 없어지지 않을까?

    - 하지만 막상 컴파일해보면 여전히 에러가 있음을 볼 수 있다.

    - 왜냐하면 if(조건식)은 실행시간에 검사를 하지만 코드를 생성하는건 컴파일할 때 하므로 *a = 0이 에러가 난다.

template<typename T>
void num(T a) {
    if constexpr(0)
        *a = 0;
}

int main() {
    int n = 0;
    
    num(&n); // T : int* - 역참조로 0을 집어넣는것으로 문제 x.   ok
    num(n);  // T : int  - int에다 역참조로 값을 넣을 수는 없다. error
}

    - 위와 같이 바꿀 경우 if constexpr은 컴파일 시간에 조건을 검사하며, 항상 false이므로 *a=0; 코드 자체를 생성할 필요가 없어진다. 그래서 컴파일을 해도 문제 없이 컴파일 됨을 볼 수 있다.

 

결론.

    - 함수 템플릿을 만들 때 조건에 따라 특정 코드를 생성하지 못하게 할 때 사용

728x90
반응형