[C++기초] 17. constrexpr, 람다 식, 가변인자 템플릿

INDEX

  1. 템플릿 메타 프로그래밍
  2. constexpr 함수, 변수
  3. constexpr 활용
  4. const vs constexpr
  5. 람다 식(Lambda Expression)
  6. 가변 인자(Variadic) 템플릿

템플릿 메타 프로그래밍

예시 : 템플릿 메타 프로그래밍

// T로 전달된 값을 계산
template <int T>
struct Fibonacci
	enum { value = (Fibonacci<T-1>::value + Fibonacci<T-2>::value) };
};

// 이 템플릿 메타프로그래밍에는 조건문이 없다.
// 그 대신 구조체 오버로딩 같은 방법을 사용하여 0, 1, 2와 같은 특수 케이스를 처리.
template<>
struct Fibonacci<0>
{
	enum { value = 1 };
};

template<>
struct Fibonacci<1>
{
	enum { value = 1 };
};

template<>
struct Fibonacci<2>
{
	enum { value = 1 };
};
//Main.cpp

// 이렇게 하면 값을 곧바로 얻음
// 값이 컴파일 시에 컴파일 되어서 들어옴
int mai()
{
	int x = Fibonacci<45>::value;
	cout << x << endl;
}

좋긴 좋은데 어려움….

왜 이런 짓을 했을까?

constexpr 함수, 변수

constexpr

예시 : constexpr함수

constexpr unsigned int fibonacci (unsigned int i)
{
    return (i<= 1u) ? i : (fibonacci(i-1) + fibonacci(i-2));
}

예시 : 함수와 constexpr

constexpr int Factorial(int n)
{
    return n <= 1 ? 1: n* Factorial(n-1);
}
int main()
{
    // 사례 1
    int value = 3;
    int result1 = Factorial(value); // OK

    // 사례 2
    constexpr int result2 = Factorial(value); // 컴파일 에러

    // 사례 3
    constexpr int result3 = Factorial(3); // OK

    // …
}

예시 : 컴파일러가 거부하는 경우

constexpr int Fibonacci(int n)
{
    if (n == 0)
    {
        return 0;
    }
    return n <= 2 ? 1 : Fibonacci(n-1) + Fibonacci(n-2);
}
int main()
{
    constexpr int result = Fibonacci(30); // 컴파일 에러
    // ...
}

constexpr 활용

constexpr활용

해쉬함수

constexpr를 활용한 해쉬 함수

허나! 여전히 런타임 중에 실행되고 있음

예시 : 컴파일 타임 문자열 해쉬

constexpr unsigned long djb2_hash_impl(const char* text, unsigned long prev_hash)
{
    return text[0] == '\0' ? prev_hash : djb2_hash_impl(&text[1], prev_hash*33^static_cast<unsigned long>(text[0]));
}

constexpr unsigned long djb2_hash(const char* text)
{
    return djb_hash_impl(text, 5381);
}

int main()
{
    constexpr unsigned long jcoco = djb2_hash("Coco");
    // ...
}

const vs constexpr

const vs constexpr

const와 constexpr

const와 constexpr함수

const constexpr
멤버 함수에만 사용 가능 멤버와 비멤버 함수에 둘다 사용 가능
멤버 변수를 바꿀 수 없음 멤버 변수를 바꿀 수 있음 (C++14부터)

배열의 길이 정하기

enum

class FixedArray
{
public:
	// ...
private:
	enum { MAX = 10 };
	int mSize;
	int mArray[MAX];
};

constexpr

class FixedArray
{
public:
	// ...
private:
	static constexpr int MAX = 10;
	int mSize;
	int mArray[MAX];
};

람다 식(Lambda Expression)

람다식

람다 식 이외의 방법으로 백테 정렬

예시 : 람다식을 이용한 벡터 정렬

#include <algorithm>
#include <vector>
int main()
{
    std::vector<float> scores;
    scores.push_back(50.f);
    scores.push_back(88.f);
    scores.push_back(70.f);
    std::sort(scores.begin(), scores.end(), [](float a, float b) { return (a>b); });
}

캡쳐 블록

캡쳐 블록 예시

매개변수 목록

매개변수 목록 예시

지정자

지정자 예시

반환형

람다 식의 장점

람다 식의 단점

베스트 프랙티스

  1. 기본적을 이름 있는 함수를 쓰자 (전통적 방식)
  2. 자잘한 함수는 람다로 써도 괜찮음(한 줄짜리 함수)
  3. 허나 재사용할 수 있는 함수를 찾기 좀 어려움
  4. 정렬 함수처럼 STL 컨테이너에 매개변수로 전달할 함수들도 좋은 후보
    • qsort()에 함수 포인터 넘겨줘야 했는데, 람다를 사용하면 확실히 더 좋음

가변 인자(Variadic) 템플릿

가변 인자 템플릿

가변 인자 템플릿 활용