2014-07-22 52 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; 
} 
相关问题