2011-01-30 5 views
4

저는 정의를 사용하여 컴파일 할 때 구성 할 수있는 C++ 수학 라이브러리에서 작업하고 있습니다.라이브러리 구성에 #define 사용

구성 중 하나가 정밀도를 정의합니다. 코드에서 보면 다음과 같습니다.

#ifdef MYMATH_USE_DOUBLE 
    typedef double Real; 
#else 
    typedef float Real; 
#endif 

잘 작동합니다.

누군가가 MYMATH_USE_DOUBLE으로 구성된 후에 라이브러리를 사용하려면 해당 정의를 컴파일러에 전달해야합니다.

더 좋은 방법이 있나요?

사용자가 수학 라이브러리를 컴파일하는 데 사용 된 정의를 기억하고 자신의 앱에서이 정의를 모두 반복해서 사용하는 것을 원하지 않습니다.

답변

1

일반적으로 가장 좋은 방법은 모든 정의가있는 파일 하나를 만드는 "configure"스크립트를 실행하는 것입니다. 이 파일은 모든 헤더에 포함되어 있습니다. 예를 들어, 소스에서 OpenSSL을 컴파일하면 "configure"는 e_os.h를 생성합니다 (이름을 기억하는 한). 모든 헤더에 실제로 포함됩니다.

+0

이것이 해결책이라고 생각합니다. 이제 선택 도구 (scons)에 헤더를 작성하는 방법이 있는지 알아야합니다. – m0tive

+0

이것은 환경 설정을 라이브러리로 컴파일하는 방법에 대한 대답입니다. 템플릿 (다른 주석에 설명되어 있음)을 사용하면 작동하지만 더 많은 코드 리팩터링이 필요하다는 것을 인정합니다. – m0tive

2

float을 사용하는 구현과 double을 사용하는 구현 (두 번째는 long double을 사용)의 두 가지 병렬 기능 세트를 제공하십시오. 이것은 C 라이브러리가하는 것입니다. double, sinf()float, sinl()long double에 대해 sin()입니다.

또는 C++에서 오버로드 또는 템플릿 사용을 고려할 수 있습니다. 내 생각에 그건 단순함보다는 오히려 혼란을 야기 할 수 있습니다. (또는 명시 적으로 접미어가 붙지 않는 한 부동 소수점 리터럴이 double이기 때문에 우세하게 오버플로가 사용됩니다) 그러나 템플릿은 종종 이러한 방법을 선택하는 방법입니다 일.

( bstamour에 의해 코멘트에 비추어 수정 댓글은 내가 너무 보수적 년대와 1990 년대 틱 당하고합니다.)

+0

이것은 C++이기 때문에 템플릿을 사용하는 것이 좋습니다. 이러한 종류의 문제는 해결하기 위해 고안된 것입니다. 또한 템플릿 시스템은 전달 된 매개 변수의 유형에 따라 템플릿 기반 유형을 유추 할 수 있으므로 사용자 관점에서 혼동하지 않아야합니다. – bstamour

2

나는 기본적으로 이중으로 템플릿을 사용하는 것이 좋습니다 것입니다. 두 배입니다으로

template <typename F = double> 
F sin(const F& r) 
{ 
//... 
} 

그런 식으로 사용자는 기능을 사용할 수 있지만 유형 변경하는 옵션이 있습니다

float f = sin<float>(r); 

편집 : 템플릿 시스템은 F가 플로트 것을 자동으로 추측한다을 이 경우에, 주어진 r은 실수이다.

+0

템플릿을 사용하는 좋은 점은 라이브러리 사용자가 함수에 사용자 정의 부동 유형을 사용할 수 있다는 것입니다. – bstamour

+0

템플릿을 사용하면 문제가 해결되지만 라이브러리의 기본 클래스에서 사용하는 데는 걱정이됩니다. 3D 앱용 행렬/퀘타/벡터를 만들고 있습니다. 저는 이론적으로 _alot_으로 사용될 4x4 Matrix 클래스와 같은 템플릿 클래스를 사용하지 않기 위해 노력하고 있습니다. – m0tive

+0

어떻게 그 클래스들을 템플릿 화하지 않겠습니까? 함수가 const 레퍼런스를 받아 들일 수 있다면 여전히 효율적인 코드를 생성하고있는 것입니다. 무거운 매트릭스 변환을 수행하는 경우 유형에 관계없이 참조로 전달하는 것이 좋습니다. – bstamour

0

lin의 헤더 파일에 조건부 정의를 넣으십시오. 아직 없으면 ans는 컴파일러 검색 지시문을 적절한 lib 파일에 배치합니다 (클라이언트에 포함될 때).

#ifdef MYMATH_USE_DOUBLE 
    typedef double Real; 
$ifndef _LIB // only for clients 
#pragma comment(lib, "double_lib") // double_lib name of the library. 
#endif 
#else 
    typedef float Real; 
$ifndef _LIB 
#pragma comment(lib, "float_lib") 
#endif 
#endif 
1

이미 다른 사람들이 잘 알고 있기 때문에 템플릿을 사용하면 문제를 해결할 수 있습니다. 그러나 일반 코드를 사용자에게 노출하면 다른 유형을 선택할 때 라이브러리를 다시 컴파일해야합니다.그것은 단지 일반 된 함수 오버로드를 사용 유형의 고정 세트로 내부적으로 일반적인 코드를 사용하여 인터페이스를 노출하는 것이 더 적합 할 수 있습니다 :은 GNU 툴체인을 가정

// generic implementation (internal linkage): 
namespace { 
    template<typename Real> 
    Real plus42(Real value) { 
     return value + 42; 
    } 
} 

// API functions (external linkage): 
float plus42(float value) { return plus42<>(value); } 
double plus42(double value) { return plus42<>(value); } 

을, 당신은 죽은 코드를 잡아 당겨 예방할 수 있습니다 컴파일러에 -fvtable-gc -ffunction-sections -fdata-sections을 전달하고 정적으로 링크 할 때는 -Wl,--gc-sections을 링커에 전달하십시오.