2014-07-22 84 views
2

我正在開發一個元編程項目,我們希望能夠將浮點數作爲模板參數傳遞。我不確定這個問題是否會更適合堆棧交換,但我認爲這是一個有點概念,所以選擇了這個網站。如何將浮點數作爲模板參數傳遞?

基本上,我想這樣做:

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) 

然而,事實證明,我可以一個指針的指針傳遞給一個對象(也許是一個struct包含一個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

使它成爲一個全球性的。 PS:你可以使用引用而不是指針。 –

+0

@ThomasEding我無法讓它工作; http://ideone.com/LGDv1j – arman

+0

你爲什麼需要它?爲什麼它必須在編譯時完成(即使用模板)?也許這是一個[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) –

回答

2

這個工作對我來說:

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

double param = 1.2; 

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

我用G ++ 4.8.2。

2

這裏的問題是,只有具有聯動對象可以用作模板非類型的地址參數,我們可以進入到C草案++標準節14.3.2模板非類型參數它說(重點煤礦看到這):

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

如果你想*pVar是一個編譯時間常數優化fun()和使用它的目的只有一個不變的是接受(例如,作爲模板參數或陣列尺寸),你需要接受它作爲const double* const,使param低於也constexpr(代碼在ideone.com here)...

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; 
} 
相關問題