메타프로그래밍으로 소수구별과 응용

메타프로그래밍이란 흔히 컴파일타임에 프로그램이 돌았던거를 컴파일타임를 연산을 시켜

런타입 시간을 줄이는 기술이다.

이 기술은 템플릿이라는 거를 응용해서 만든 기술이다.

템플릿은 기본적으로 컴파일 타입때 타입체킹등 값을 미리 넣는 작업을 한다.

소수 구하는 함수는 다음과  같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
template <int Q, int B>
struct isPrime_Imple {
    enum { value = Q%B!=0 && isPrime_Imple<Q,B1>::value  };
};
template <int Q>
struct isPrime_Imple<Q,2> {
    enum { value = Q%2!=0 };
};
template <int Q>
struct isPrime {
    enum { value = isPrime_Imple<Q, Q / 2>::value  };
};
template <>
struct isPrime<0> {
    enum { value = true};
};
template <>
struct isPrime<1> {
    enum { value = false };
};
template <>
struct isPrime<2> {
    enum { value = true };
};
template <>
struct isPrime<3> {
    enum { value = true };
};
int main(){
    std::cout << isPrime<1>::value;
    return 0;
}
cs

해당 소스를 컴파일 시키고 디스어셈을 보자.


흔히 런타입때 이와같이 만들면 보통 call연산을 통해 값을 값을 계산하지만

이와같이 바로 0이라는 값이 박혀있다.

이 특성을 이용해서  다른걸 만들어보자.

특정 배열의 사이즈가 소수일때 도는 로직과 소수가 아닐때 돌아가는 로직을 컴파일 타입에 구현해보자

코드는 아래와같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// template.cpp: 콘솔 응용 프로그램의 진입점을 정의합니다.
//
#include “stdafx.h”
#include <iostream>
#include <array>
template <int Q, int B>
struct isPrime_Imple {
    enum { value = Q%B!=0 && isPrime_Imple<Q,B1>::value  };
};
template <int Q>
struct isPrime_Imple<Q,2> {
    enum { value = Q%2!=0 };
};
template <int Q>
struct isPrime {
    enum { value = isPrime_Imple<Q, Q / 2>::value  };
};
template <>
struct isPrime<0> {
    enum { value = true};
};
template <>
struct isPrime<1> {
    enum { value = false };
};
template <>
struct isPrime<2> {
    enum { value = true };
};
template <>
struct isPrime<3> {
    enum { value = true };
};
template <int SZ,  bool = isPrime<SZ>::value >
struct Helper;
template <int SZ>
struct Helper<SZ, false>
{
    enum { value = false };
};
template <int SZ>
struct Helper<SZ, true>
{
    enum { value = true};
};
template <class T,size_t SIZE>
void fn(std::array<T, SIZE> a) {
    std::cout << Helper<SIZE>::value;
}
int main(){
    std::array<int10> a{};
    fn(a);
    return 0;
}
cs

소수인지 아닌지를 판별하는 거를 만들기위해 Helper를 따로 작성하였고,

해당 특성을 특수화 처리하여 두번째 값이 true인지 false를 체크하는 기능을 만들고 fn함수에서 이 값을 마치 변수처럼 쓸수 있게 만들었다.

정말 컴파일계산되어있나 어셈을 보자.

 

답글 남기기

이메일 주소는 공개되지 않습니다.