问题描述
正在尝试实现某些内容并提出一些问题,但所有的追逐都归结为:
是否可以构建一个工具来强制执行 constexpr
函数的编译时评估?
int f(int i){return i;}
constexpr int g(int i){return i;}
int main()
{
f(at_compilation(g,0));
int x = at_compilation(g,1);
constexpr int y = at_compilation(g,2);
}
在所有情况下, at_compilation
强制执行 g
的编译时评估。
at_compilation $ c $
- 任何(数字原生)文字类型作为输出,这是constexpr函数调用的结果。
- 这也可以基于函数返回类型进行硬编码。
Desirables
- 减少宏的使用,但不要害怕使用。
- 是一般的(不是硬编码类型)。
- 支持任何文字类型。
相关问题:
- (此示例有
AT_COMPILATION
macro) - Allow any (numerical native) literal type as input for the constexpr function.
- this could also be hardcoded based on the function arguments types.
- Allow any (numerical native) literal type as output, which is the result of the constexpr function call.
- this could also be hardcoded based on the function return type.
- Reduced macro usage but don't be afraid of using.
- Be general (not type hardcoded).
- Support any literal type. At last any numerical native literal type is a requirement.
- When does a constexpr function get evaluated at compile time?
- Forcing a constant expression to be evaluated during compile-time?
- Passing any function as a template parameter?
- Where in the C++11 standard does it specify when a constexpr function can be evaluated during translation?
所有代码示例都对要求有限制。
一个清楚的解释,如何这是不可行的C + +也是一个很好的答案。
我怀疑这是不可能的基于 / ,其中说明且结果也用于常量表达式。这不是我以前关于 constexpr
函数的一部分,我首先认为只是传递文字(或其他编译时输入)作为参数足以保证(通过标准)
已经假设constexpr函数的目的是在必要时可以适用于常量表达式的情况,就像数组边界一样。没关系。鉴于此,这个问题是关于使用它们作为编译时计算的工具。
我认为这是不可能的,因为编译器只需要计算在编译时使用的值,并且没有可以使用类类型的值的每个部分的通用表达式。初始化私有成员的计算可能是不可能强制的,因为你将依赖于一个公共的constexpr成员函数来使用结果。
如果你可以访问对象表示
static_cast< char const *>(static_cast< void const *>(& const_value))
可能对计算结果进行校验(并将结果用作积分常数表达式),迫使编译器执行并非所有计算。但是在常量表达式中不允许从 void *
到 char *
的转型,同样试图完成与联合
。即使允许,如果构造函数留下一个字节未初始化,使用未初始化的值也被禁止在常量表达式。
所以,即使C ++有更好的工具对于内省,仍然不可能恢复由constexpr函数执行的工作,以便人为地使用一些成员,而不是其他成员。
只是为了清楚(即使它重复的问题),没有理由想要这个。如果需要,语言已经需要检查所有在编译时是否可以计算,并且强制编译器非延迟计算纯值的唯一效果将是使其更慢并使用更多的内存。
编辑(问题已彻底改变)
如果你有几个函数返回标量类型,确保其中一些在某些参数下作为常量表达式工作,然后使用 static_assert
编写测试用例。
constexpr int g(int i){return i;}
int i = 5;
static_assert(g(3)== 0,failure 1);
static_assert(g(i)== 5,failure 2);
如果您不想修复结果值,请舍弃它们。 (很抱歉,GCC 部分表达式,因此您可能需要在该平台上执行更多的巴洛克式。
static_assert(g(i)== 5 || true,失败只有不是constexpr);
链接的问题似乎解决了很多如果你想扩大这些答案或修复一个特定的错误,最好是解释这个错误,而不是要求我们阅读这么多的文学,从头开始。
@cyberpunk_ is trying to achieve something and made some questions about it but all the chase boils down to this:
Is it possible to build a tool to enforce compile-time evaluation of a constexpr
function?
int f(int i) {return i;}
constexpr int g(int i) {return i;}
int main()
{
f(at_compilation(g, 0));
int x = at_compilation(g, 1);
constexpr int y = at_compilation(g, 2);
}
In all situations, at_compilation
enforce compilation-time evaluation of g
.
at_compilation
doesn't need to be in this form.
Requirements
Desirables
Related Questions:
Answers with relevant code samples:
All the code samples have limitations regarding the requirements.
A clear explanation for how this is unfeasible in C++ is also a good answer.
I suspect it's impossible based on @K-ballo / @Herb Sutter answer which states "and the result is used in a constant expression as well". This was not part of my former conception about constexpr
functions, I firstly thought that just passing literals (or other compile-time input) as arguments would suffice to guarantee (by standard) it to be evaluated at compilation-time.
It's already assumed constexpr function's purpose is that they can fit in constant expression situations when necessary, like in array bounds. That's OK. Given that, this question is about a hack on using them just as a tool for compile time calculation. Whether it's a good or bad thing to do should not matter.
I believe that it's impossible because the compiler is only required to compute values that are used at compile-time, and there is no generic expression that can use every part of a value of class type. Computations that initialize private members might even be impossible to force, as you would depend on a public constexpr member function to use the result.
If you could access the object representation by
static_cast< char const * >( static_cast< void const * >( & const_value ) )
then it would be possible to checksum the result of the computation (and use the result as an integral constant expression), forcing the compiler to perform every calculation that isn't moot. But the cast from void *
to char *
is disallowed in a constant-expression, and likewise attempting to accomplish the same with a union
. Even if it were allowed, if the constructor left one byte uninitialized, using an uninitialized value is also forbidden in a constant-expression.
So, even if C++ had better tools for introspection, it would still be impossible to recover the work performed by a constexpr function in order to artificially use some members but not others.
Just to be clear (even if it repeats the question), there's no reason to want this. The language already requires a check that everything can be computed at compile time, if needed, and the only effect of forcing the compiler to non-lazily compute pure values would be to make it slower and use more memory.
Edit (question was radically altered)
If you have several functions returning scalar type, and want to ensure that some of them work as constant expressions under certain arguments, then write test cases using static_assert
.
constexpr int g(int i) {return i;}
int i = 5;
static_assert( g( 3 ) == 0, "failure 1" );
static_assert( g( i ) == 5, "failure 2" );
If you don't want to fix the result values, then discard them. (Unfortunately, GCC may optimize out the non-constant part of such an expression, so you might need to do something more baroque on that platform.
static_assert( g( i ) == 5 || true, "failure only if not constexpr" );
As for encapsulating this into a macro, the other linked questions seem to address a lot. If you want to expand one of those answers or to fix a particular bug, it would be better to explain the bug rather than ask us to read so much literature and start from scratch.
这篇关于单个表达式帮助器的编译时强制执行constexpr函数的可能性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!