是真的需要constexpr吗? [英] Is constexpr really needed?

查看:119
本文介绍了是真的需要constexpr吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在看着C ++的新的constexpr特性,我不完全理解它的需要。



例如,下面的代码:

  constexpr int MaxSize()
{
...

return ... ;
}

void foo()
{
int vec [MaxSize()];
}

可以替换为

  int MaxSize()
{
...

return ...;
}

static const int s_maxSize = MaxSize();

foo()
{
int vec [s_maxSize];
}

更新

第二个例子实际上不是标准的ISO C ++(感谢几个用户指出这一点),但某些编译器(例如gcc)支持它。所以不是const使程序有效,而是gcc支持这个非标准的特性。 (据我所知,这是可能的,只有当数组被定义为局部的函数或方法,因为全局数组的大小仍然必须在编译时知道。)如果我编译没有选项-std = c + +98 -pedantic-errors,甚至代码

  int MaxSize()
{
return 10 ;
}

void foo()
{
int vec [MaxSize()];
}

将使用gcc编译。



因此,我将考虑到目前为止的反馈(以及我在同一时间进行的一些进一步的阅读),尝试改写我的问题。



我使用const关键字。使用const可以定义一个在其整个生命周期内具有一定值的常量。可以使用任何表达式初始化常量,该表达式被计算一次,即创建常数时。对于这些情况,我认为constexpr是相当无用的:它将引入一个非常小的优化,定义常量值的表达式将在编译时而不是运行时计算。每次我需要一个复杂的初始化运行时常数我使用关键字const。



所以constexpr可能会派上用场的情况下,我们需要初始化一个常量编译时间。一个例子是向量定义:标准不支持在运行时定义大小。另一个例子是一个包含一个或多个非类型参数的模板。



在这种情况下,我通常使用宏:

  #define MAX_SIZE(10)

void foo()
{
int vec [MAX_SIZE];
}

但是,如果我理解正确,constexpr函数比宏更强大它们允许在其定义中递归调用constexpr函数。但是,我不能想到任何实际的应用程序,我曾经想要使用这样一个复杂的计算来定义一个编译时常数。



因此,即使它可能一个有趣的功能,我仍然想知道是否需要(即多少次它可以解决宏是不够的情况)。

解决方案

int vec [s_maxSize]; 在第二个例子中实际上是非法的,所以这是不可能在C ++。但你的第一个例子是完全合法的C ++ 0x。



所以有你的答案。你实际上不能做你在C ++中提出的建议。它只能在C ++ 0x中使用 constexpr 来完成。



我也想指出,这个代码也适用于C ++ 0x。在C ++中这样做需要一些真正的类模板。

  constexpr unsigned int gcd(unsigned int const a,unsigned int const )
{
return(a< b)? gcd(b,a):((a%b == 0)?b:gcd(b,a%b));
}

char vec [gcd(30,162)];

当然,在C ++ 0x中,你还必须使用三元运算符而不是if语句。但是,它工作,仍然是很容易理解比你将强制在C + +中使用的模板版本:

  template< unsigned int a,unsigned int b> 
class gcdT {
public:
static unsigned int const value = gcdT< b,a%b> :: value;
};

template< unsigned int a>
class gcdT< a,0> {
public:
static unsigned int const value = a;

};

char vec [gcdT< 30,162> :: value];

然后,当然,在C ++中,你还必须写 gcd 函数,如果你需要在运行时计算的东西,因为模板不能使用在运行时变化的参数。和C ++ 0x将有额外的优化提升知道的函数的结果完全由传递的参数,这是一个事实,只能用C ++中的编译器扩展表达的事实。


I have been looking at the new constexpr feature of C++ and I do not fully understand the need for it.

For example, the following code:

constexpr int MaxSize()
{
    ...

    return ...;
}

void foo()
{
    int vec[MaxSize()];
}

can be replaced by:

int MaxSize()
{
    ...

    return ...;
}

static const int s_maxSize = MaxSize();

foo()
{
    int vec[s_maxSize];
}

Update

The second example is actually not standard ISO C++ (thanks to several users for pointing this out) but certain compilers (e.g. gcc) support it. So it is not const that makes the program valid, but the fact that gcc supports this non-standard feature. (To my knowledge, this is possible only when the array is defined as local to a function or method, since the size of a global array must still be known at compile time.) If I compile without the options "-std=c++98 -pedantic-errors", even the code

int MaxSize()
{
    return 10;
}

void foo()
{
    int vec[MaxSize()];
}

will compile with gcc.

So I will try to rephrase my question taking into account the feedback that came so far (and also some further reading I have done in the mean time).

I use the const keyword heavily. With const I can define a constant that has a certain value during its whole lifetime. A constant can be initialized with any expression, which is evaluated once, namely when the constant is created. For these cases, I think that constexpr is pretty useless: it would introduce a very small optimization in that the expression defining the constant value would be computed at compile time instead of run time. Every time I need a run-time constant with a complex initialization I use the keyword const.

So constexpr may come in handy in situations where we need to initialize a constant at compile time. One example is a vector definition: the standard does not support defining the size at runtime. Another example is a template with one or more non-type parameters.

In such cases I normally use macros:

#define MAX_SIZE (10)

void foo()
{
    int vec[MAX_SIZE];
}

but, if I understand correctly, constexpr functions are more powerful than macros, since they allow recursive calls of constexpr functions in their definition. However, I cannot think of any practical application in which I ever wanted to use such a complex computation to define a compile-time constant.

So, even if it may be an interesting feature, I still wonder if it is needed (i.e. how often it can solve situations where macros are not enough). Maybe looking at a few real-life examples that cannot be solved with macros would help me to change this opinion.

解决方案

int vec[s_maxSize]; is actually illegal in the second example, so that is not possible to do in C++. But your first example is perfectly legal C++0x.

So there's your answer. You can't actually do what you propose in C++. It can only be done in C++0x with constexpr.

I would also like to point out, that this code also works in C++0x. Doing this in C++ would require some really fancy class templates.

constexpr unsigned int gcd(unsigned int const a, unsigned int const b)
{
   return (a < b) ? gcd(b, a) : ((a % b == 0) ? b : gcd(b, a % b));
}

char vec[gcd(30, 162)];

Of course, in C++0x you still have to use the ternary operator instead of if statements. But, it works and is still a lot easier to understand than the template version you'd be force to use in C++:

template <unsigned int a, unsigned int b>
class gcdT {
 public:
   static unsigned int const value = gcdT<b, a % b>::value;
};

template <unsigned int a>
class gcdT<a, 0> {
 public:
   static unsigned int const value = a;

};

char vec[gcdT<30, 162>::value];

And then, of course, in C++ you'd still have to write the gcd function if you needed to compute things at runtime because the template can't be used with arguments that vary at runtime. And C++0x would have the additional optimization boost of knowing that the result of the function is completely determined by the passed in arguments, which is a fact that can only be expressed with compiler extensions in C++.

这篇关于是真的需要constexpr吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆