2014-07-22 2 views
2

것은 내가 메타 프로그래밍 프로젝트를 진행하고, 우리는 템플릿 인수로 부동 소수점 숫자를 전달할 수있는 능력을 가지고 싶습니다. 나는이 질문이 Stack Exchange에 더 잘 맞을 지 확신 할 수 없었지만, 다소 개념적으로이 사이트를 선택했다.어떻게 부동 소수점 숫자를 템플릿 매개 변수로 전달할 수 있습니까?

는 기본적으로,이 작업을 수행 할 수 :

template <double var> 
double fun() { return var; } 

int main() 
{ 
    double myDoble = fun<1.0>(); 
    return 0; 
} 

물론,이 작업을 수행 할 수 없습니다. 이 링크 (http://en.cppreference.com/w/cpp/language/template_parameters)을 만드는 분명히 템플릿 인수로 전달 유형은 다음 중 하나가 될해야 :

integral type 
enumeration 
pointer to object or to function 
lvalue reference to object or to function 
pointer to member object or to member function 
std::nullptr_t (since C++11) 

그러나, 사실은 내가 구조체에 아마도 객체 (포인터를 포인터를 전달할 수 있다는 double을 포함하고 있는가?)는 그와 같은 double에 대한 포인터를 전달함으로써 위의 것을 달성 할 수있는 방법이 있을까 궁금하게 만든다.

그래서 나는이 시도 :

다음과 같은 오류 제공
template <double* pVar> 
double fun() 
{ 
    return *pVar; 
} 

int main() { 
    static const double param = 1.2; 
    double value = fun<&param>(); 
    return 0; 
} 

:

prog.cpp:9:29: error: ‘& param’ is not a valid template argument of type ‘double*’ because ‘param’ has no linkage 
    double value = fun<&param>(); 

나는 문제가 나는 원시적를 사용하고 있음을 할 수 있다는 생각을, 그래서 나는이 시도 :

를 동일한 오류를 범
struct D 
{ 
    double val; 
}; 

template <D* pD> 
double fun() 
{ 
    return pD->val; 
} 

int main() { 
    static const D d{1.2}; 

    double value = fun<&d>(); 
    return 0; 
} 

.

사람이 문제를 접근에 대한 다른 아이디어가 있습니까? 나는 사람들이 "할 수 없다"라는 대답을 자제 할 수 있다면 감사 할 것이다. 나는 그것을 할 수 없다는 것을 알고, 어쨌든 그것을하고 싶다! ;)

+0

는 글로벌하십시오. 추신 : 포인터 대신 참조를 사용할 수 있습니다. –

+0

@ThomasEding 나는 그것을 일하게 할 수 없다. http://ideone.com/LGDv1j – arman

+0

왜 필요한가요? 왜 컴파일시 (예 : 템플릿 사용)에 완료해야합니까? 어쩌면 그것은 [XY 문제] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) –

답변

2

이것은 나를 위해 작동 : 나는 g ++ 4.8.2를 사용하고 있습니다

template <double* pVar> 
double fun() 
{ 
    return *pVar; 
} 

double param = 1.2; 

int main() { 
    double value = fun<&param>(); 
    return 0; 
} 

.

2

여기서 문제는, 우리가 (강조 광산 말한다 표준 섹션 14.3.2템플릿 이외의 형태 인수 ++ 초안 C로 이동하여 볼 수 있습니다 만 템플릿이 아닌 유형의 주소를 인수로 사용할 수 있습니다 연결 개체이다) :

A template-argument for a non-type, non-template template-parameter shall be one of:

다음과 같은 총알과 같습니다

a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage [...]

당신의 오류라고 정확히 무엇 :

[...]because ‘param’ has no linkage

우리는 몇 가지 예외를 제외하고 그 블록 범위 변수를 볼 수는없는 연결이 절 3.5에 포함되지 않은 말한다 프로그램과 연계 :

Names not covered by these rules have no linkage. Moreover, except as noted, a name declared at block scope (3.3.3) has no linkage. A type is said to have linkage if and only if:

과에 대한 예외를 포함하지 않는다 이 경우.

static double param = 1.2; 

int main() 
{ 
    double value = fun<&param>(); 
    return 0; 
} 
2

을 원하는 경우 *pVarfun()을 최적화하고 사용의 목적을 위해 일정한 컴파일 시간이 될 만 상수 수락입니다 (:

것은이 경우 문제를 해결, 전 세계적으로 그것을 것입니다 선언 예를 들어 템플릿 매개 변수 또는 배열 차원)으로, 당신은 const double* const로 받아들이고해야 paramideone.com here에서 또한 아래 constexpr (코드) ... 수

template <int n> 
struct S { }; 

template <const double* const pVar> 
double fun() 
{ 
    S<(int)*pVar> s; 
    return *pVar; 
} 

constexpr double param = 1.2; 

int main() 
{ 
    double value = fun<&param>(); 
} 

코드의 다른 위치에서 동일한 값을 갖는 double의 고유 한 포인터를 템플릿에 제공하면 실행 파일에서 서로 다른 인스턴스가 생성됩니다 (예 : 무의미한 "코드 팽창", 전문화 시도 실패 ...).

2

실제로 템플릿 함수에 double을 전달하려면 래퍼를 사용해야합니다.

struct D 
{ 
    operator double(){ return 1.2; } 
}; 

template <typename T> 
double fun() 
{ 
    T t; 
    return t; 
} 

int main() 
{ 
    double value = fun<D>(); 
    return 0; 
} 

하지만 어쩌면 더 유용이 같은 매크로를 정의하는 것입니다 : 일이 같이

#define DBLWRAPPER(dbl) typedef struct { operator double(){ return dbl; } } 

int main() 
{ 
    DBLWRAPPER(1.2) DBL1_2; 
    DBLWRAPPER(2.45) DBL2_45; 

    double value1_2 = fun<DBL1_2>(); 
    double value2_45 = fun<DBL2_45>(); 
    return 0; 
} 
관련 문제