2010-03-11 4 views
0

std :: string 또는 char *를 반환하는 전 처리기 지시문을 쓸 수 있습니까?문자열을 얻기위한 전처리 지시문 작성

예를 들어 정수의 경우 :

#define square(x) (x*x) 

int main() 
{ 
    int x = square(5); 
} 

나는 동일한 기능을 수행 할 찾고 있어요하지만 스위치의 경우 패턴처럼 문자열. 1을 통과하면 "1"을 반환하고 "2"는 2를 반환해야합니다.

+4

정상적인 기능이 아닌 이유는 무엇입니까? –

+0

마틴 (Martin)이 말했듯이'square()'매크로 예제는 매크로를 잘못 작성하는 것이 쉬운 이유 중 하나를 보여줍니다. 'square()'매크로는'square (1 + 4)'와 같은 문제를 피하기 위해'#define square (x) (x) * (x))와 비슷해야한다. 그 수정, 부작용이 인수와 잘못된 동작을 방지하기가 어렵습니다. 함수는 이러한 문제를 피하고 성능에 눈에 띄는 영향을 미치지 않을 것입니다 (특히 인라인으로 만들 수있는 경우). –

+0

간단한 매크로 나 인라인 함수를 사용하면 컴파일 타임이나 런타임에만 성능이 향상됩니까? – cpx

답변

2

C++의 매크로에서는이 작업을 수행하지 않으려 고합니다. 함수는 괜찮 : 마찬가지로

char const* num_name(int n, char const* default_=0) { 
    // you could change the default_ to something else if desired 

    static char const* names[] = {"Zero", "One", "Two", "..."}; 
    if (0 <= n && n < (sizeof names/sizeof *names)) { 
    return names[n]; 
    } 
    return default_; 
} 

int main() { 
    cout << num_name(42, "Many") << '\n'; 
    char const* name = num_name(35); 
    if (!name) { // using the null pointer default_ value as I have above 
    // name not defined, handle however you like 
    } 
    return 0; 
} 

, 평방 함수해야한다고 : 실제로 평방 매우 유용 아니지만

inline int square(int n) { 
    return n * n; 
} 

(방금 직접 곱 것입니다.)

내가 (위의 기능이 괜찮)이 경우에는 권하고 싶지 않다 불구하고 호기심으로

,하는 templat 전자 메타 프로그래밍 상응하는 것이 다음 TMP 예에 실패 기본 방법은 당신이 어떤 INT 대신 컴파일 시간 상수를 사용할 필요가있다

template<unsigned N> // could also be int if desired 
struct NumName { 
    static char const* name(char const* default_=0) { return default_; } 
}; 
#define G(NUM,NAME) \ 
template<> struct NumName<NUM> { \ 
    static char const* name(char const* default_=0) { return NAME; } \ 
}; 
G(0,"Zero") 
G(1,"One") 
G(2,"Two") 
G(3,"Three") 
// ... 
#undef G 

하는 것으로. 나는이 추가 단계를 보라

#define STRING_1() "ONE" 
#define STRING_2() "TWO" 
#define STRING_3() "THREE" 
... 

#define STRING_A_NUMBER_I(n) STRING_##n() 

#define STRING_A_NUMBER(n) STRING_A_NUMBER_I(n) 

내가 이것을 본

+0

이 문제는 템플릿 metaprogramming으로 어떤 문제를 해결할 수 있는지 궁금합니다. –

+0

@Chris : 물론, NumName :: name()'(call 인라인 정적 함수)를 사용하고 관심있는 모든 값을 전문으로합니다. 그러나 나는 필요성을 보지 못합니다. –

+0

@Roger - 더 큰 숫자를 더 작은 수의 조합으로 단순화하는 깔끔한 트릭을 수행 할 수 있는지 궁금합니다. 템플릿 시스템은 범위를 허용하지 않습니다 (예 :'template <> struct NumName <21-29>') 그래서 그것은 매우 유용하게 끝나지 않습니다. –

1

#define 전 처리기 지시문은 소스 코드의 문자열을 대체합니다. 당신이 원하는 case...when 구조는 여전히 사소한되지 않습니다 :

#define x(i) ((i)==1?"One":((i)==2?"Two":"Many")) 

는 시작이 될 수도 -

#define x(i) xsof[max(0, min((i)-1, (sizeof xsof/sizeof xsof[0] - 1)))] 

더 합리적이고 더 나은 성능 보인다

static char* xsof[] = ["One", "Two", "Many"]; 

좋아하지만 정의 뭔가.

: Chris Lutz의 제안에 따라 두 번째 매크로는 자동으로 xsof 정의로 조정됩니다. 마크 당 1 위를 기록했다.

+2

매크로의 '2'를'(sizeof xsof/sizeof xsof [0] - 1)'로 변경하면 훌륭한 유지 보수가 가능한 솔루션을 얻을 수 있습니다. –

+0

주어진 매크로의'(i)'는 실제로'(i) - 1'이 아니어야합니까? –

+0

@Michael, 아 그래, 한 번 편집에서 고치기를 원한다고 말했다. @ 크리스, 좋은 생각, 그것을 통합 편집. –

0

정수를 문자열로 변환 할 수 없으므로 각 값을 열거하지 않는 한 1 -> "1", 2 -> "2"등이됩니다.

당신은 C 프리 프로세서와 문자열로 인수 값을 변환 할 수 있습니다

#define STRINGIZER(x) #x 
#define EVALUATOR(x) STRINGIZER(x) 
#define NAME(x)   EVALUATOR(x) 

NAME(123) // "123" 

#define N 123 
#define M 234 

NAME(N+M) // "123+234" 

SO 1489932를 참조하십시오.

1

...이, 당신이 1 + 2를 통과하면 STRING_A_NUMBER_I에 전달하기 전에,이 3으로 변환됩니다, 그래서 확인 n이 평가하는 것입니다 조금은 피하는 것, 누군가 정교 할 수 있니?

+0

Boost는이 방법을 사용하여 전처리 코드 생성 작업을 수행합니다. 그 모든 것이 어떻게 작동 하는지를 해독하는 것은 재미있었습니다. 또한 @Chris Lutz, "STRING _ ## n"에 개폐식 대괄호가있는 경우 작동합니다 –

+0

여기에 고유 번호로 STRING_X을 (를) 정의 할 수 있습니까? – cpx

+0

@Dave : 정확히 무슨 뜻인지 잘 모르겠다 죄송합니다. 또한 실제 숫자로 전달해야합니다. 예를 들어 1 + 2는 통과 할 수 없으며 3을 전달해야합니다. – matt