2014-08-29 3 views
2

문자열 리터럴을 사용하고 정수를 생성하는 컴파일 타임 해시를 만들려고했습니다. 나는 Code :: Blocks의 GCC 4.7.1 컴파일러 (이전에 나에게 침입했다)를 사용하고있다.C++ 컴파일 타임 고유 ID 생성기는 항상 동일한 값을 반환합니다.

typedef unsigned long long ull; //less typing 

constexpr ull basis = 14695981039346656037ULL; //Don't ask me 
constexpr ull prime = 1099511628211ULL; //Someone else invented them 

template <size_t I> 
constexpr ull myhash(const char* p, ull b) //Recursive function 
{ 
    return myhash<I - 1>(p, (b^p[I]) * prime); 
} 

template <> 
constexpr ull myhash<size_t(-1)>(const char* p, ull b) //Base case 
{ 
    return b; 
} 

//This macro generates a variable of a given name with a hash of that name 
#define CTH_GEN(x) constexpr ull x = myhash<sizeof("x") - 2>("x", basis) 

my_hash의 재귀 부분은 문자열의 끝에서 시작하여 그 수를 반환하는 기본 케이스를 돌 때까지 지속적으로 문자열의 문자 수 b 변경됩니다 : 이것은 작동하는 방법이다. 매크로는 변수 이름과 해시가 항상 일치하도록하여 잠재적 버그 가능성을 줄입니다. 나는 이런 식으로 테스트 constexpr unsigned long long A = my_hash<sizeof("A") - 2>("A", basis)CTH_GEN(A) 평가 것 :

CTH_GEN(A); 
CTH_GEN(B); 
CTH_GEN(C); 

int main() 
{ 
    cout << ((basis^'A') * prime) << " : " << A << endl; 
    cout << ((basis^'B') * prime) << " : " << B << endl; 
    cout << ((basis^'C') * prime) << " : " << C << endl; 
} 

이 테스트 실행의 출력입니다 :

12638222384927744748 : 12638214688346347271 
12638225683462629381 : 12638214688346347271 
12638224583951001170 : 12638214688346347271 

숫자는 각면에 동일해야합니다. 왼쪽은 해쉬의 런타임 계산이고, 오른쪽은 컴파일 타임 계산입니다. 둘 다 같은 순서로 똑같은 수학을 사용하지만, 컴파일 타임 버전은 항상 동일한 숫자를 생성합니다. 나는 이것을 설명하는 설명, 해결 방법 또는 완전히 새로운 방법에 정말로 감사 할 것입니다. 내가 사용하고있는 특정 해시 방법은 완전히 변경 될 수 있지만 완전히 다른 질문이라고 생각합니다.

답변

2

"x" 매크로 매개 변수 x을 문자열로 바꾸지 않습니다. 리터럴 문자열 "x"의 약자입니다.

매크로 매개 변수를 문자열로 바꾸려면 # 연산자 , #x을 사용하십시오.

+1

OHMYGOD 감사합니다. 나는 실제로 파운드 기호가 매크로에서 무엇을하는지 봤고 C를 계속 넌센스로 만들었다. 나는 그것을 찾지 못했다고 나는 믿을 수 없다! – Bob