2014-06-20 120 views
2
#include <algorithm> 

struct S 
{ 
    static constexpr int X = 10; 
}; 

int main() 
{ 
    return std::min(S::X, 0); 
}; 

如果std::min需要一个const int&,编译器很可能想有S::X还定义了某个地方,即S::X必须的存储器中存在。力constexpr在编译时进行评估

参见herehere

有没有办法force编译器在编译时评估我的constexpr

的原因是:

最初,我们在init优先静态变量的初始化初出现了问题。有一些struct Type<int> { static int max; };,和一些全球static int x = Type<int>::max;,和一些其他早期代码other_init使用,即x。当我们更新GCC时,突然我们在other_init中有x == 0

我们认为我们可以通过使用constexpr来避免这个问题,因此它总会在编译时评估它。

唯一的另一种方法是使用struct Type<int> { static constexpr int max(); };来代替,即让它成为函数。

+3

'constexpr'不能解决静态初始化订购Fiasco。 – chris

+0

你可以发布给你的代码吗?我的意思是结构类型为的那个。我有兴趣看到它。 –

+0

@MarcoA .:你的意思是什么代码?它已经在那里。让'other_init'成为__attribute __((构造函数))',然后'printf(“%i”,x);'。 – Albert

回答

3

constexpr在编译时进行评估。你的问题是 由于事实std::min不是constexpr,所以 无论其输入的,结果不是一个常量表达式 (特别是,如果初始化使用std::min静态 寿命的变量,它是动态的初始化)。

最简单的解决方案可能是定义你自己的min, 东西沿着线:

template <typename T> 
constexpr T staticMin(T a, T b) 
{ 
    return a > b ? b : a; 
} 

这将导致在编译时全面评估,并 静态初始化。

+2

我的问题不是关于'std :: min'。这只是一个例子。我不想复制所有的STL。另外,'std :: min'的结果不是一个常量表达式并不重要。我不想/需要/在编译时要求评估'std :: min'。 – Albert

+0

那么你的问题是什么?在你的示例代码中,'S :: X'是一个编译时间常量,它在编译时被评估。在编译时不评估的是'std :: min',因为'std :: min'不是'constexpr'。 –

+0

我不在乎'std :: min'在编译时不被评估。'S :: X'不在编译时进行评估,否则链接器不会抱怨丢失的符号。另请参阅我的链接问题,也许他们更清楚。 – Albert

0

对于被允许存在的模板值参数类型,你可以引入一个数据结构是这样的:

template <typename T, T K> 
struct force 
{ 
    static constexpr T value = K; 
}; 

用法:

force<int, std::min(S::X, 0)>::value