is_constant_evaluated() 应该产生 constexpr 变量吗?
is_constant_evaluated() should produce constexpr variables?
我已经阅读了std::is_constant_evaluated()
定义,但我仍然不确定为什么(1)不适用于最新的GCC:error: 'x' is not a constant expression
template<auto v>
struct s
{};
constexpr void f(int x)
{
if (std::is_constant_evaluated())
{
// constexpr int z=x; (1)
// s<x> a; (2)
}
}
int main(int argc, char* argv[])
{
f(4);
//f(argc);
return 0;
}
- 按照标准,这应该有效吗?
- 或者只是 GCC 实施有问题?
- 我能以某种方式实现预期的行为吗?这基本上是:
在std::is_constant_evaluated()
上分支
- 如果是真的:代码可以使用变量作为 constexpr(如 (2))
- 如果为 false:代码使用变量作为非 constexpr
更新
我可以将 constexpr-essiveness 信息"传输"到函数中吗?基本上是在f()
中决定是否使用constexpr
x 调用。
更新关于我想要实现的目标的更复杂的示例:如果可能,此示例应在编译时字符串化参数。
template<auto v>
struct dummy_stringify
{
static constexpr auto str=v==4 ? "4" : "31"; // this is just an example; imagine here a much more complex logic
};
constexpr void f(int x)
{
if (std::is_constant_evaluated())
{
std::puts("A compile time calculation:");
//std::puts(dummy_stringify<x>::str);
} else
{
std::cout<<"A runtime calculation:"<<std::endl;
std::cout<<x<<std::endl;
}
}
int main(int argc, char* argv[])
{
f(4);
f(argc);
return 0;
}
无论如何计算f
本身,x
都不是常量表达式。这是一个常规if
(如何使用is_constant_evaluated
)。它不是一个丢弃的分支,因此它必须包含格式正确的代码,即使f
不是常量计算的。当x
不是常量表达式时,函数仍将包含该(未执行的)分支,并且它将尝试在需要常量表达式的地方使用x
。这显然是格式错误的。
海湾合作委员会不接受它是非常正确的。
这里的基本问题是,即使在常量计算期间(以及在is_constant_evaluated
检查下)调用constexpr
(甚至consteval
)函数,所有参数值之间仍然只有一个函数共享。因此,您永远不能将函数参数用作常量表达式(即使使用该参数的调用是常量表达式)。 如果需要常量表达式参数,它必须是模板参数。
更新
我找到了一个带有小助手类的解决方案(当然可以使用std::integral_constant
)
template<auto val_>
struct val
{
static constexpr auto value=val_;
};
template<auto v>
struct dummy_stringify
{
static constexpr auto str=v==4 ? "4" : "31"; // this is just an example; imagine here a much more complex logic
};
#include <iostream>
using namespace std;
template<class T>
constexpr void f(T x)
{
if constexpr(requires{ T::value; })
{
std::puts("A compile time calculation:");
std::puts(dummy_stringify<T::value>::str);
} else
{
std::cout<<"A runtime calculation:"<<std::endl;
std::cout<<x<<std::endl;
}
}
int main(int argc, char* argv[])
{
f(val<4>{});
f(argc);
return 0;
}
可以通过template<char...> auto operator""_v();
来改进它f(4_v)
相关文章:
- vs 2015 constexpr变量不恒定,但与2019相比还好吗
- constexpr函数中的静态constexpr变量
- 有时可以在 constexpr 上下文中使用非 constexpr 变量?
- 错误:constexpr 变量'struct2Var'必须由常量表达式初始化
- 是否使用静态 constexpr 变量 odr?
- 是否可以将变体的索引作为 constexpr 变量获取?
- 非 constexpr 变量模板的开销是否为零?
- Constexpr变量不是编译时值
- 为什么非成员静态 constexpr 变量不是隐式内联的?
- 使用 constinit 变量初始化 constexpr 变量
- 这是通过初始化 constexpr 变量来标记编译错误的合理跳转
- "static initialization order fiasco"是 constexpr 变量的问题吗?
- lambda 表达式中引用捕获的 constexpr 变量和非显式捕获的 constexpr 变量之间的区别
- is_constant_evaluated() 应该产生 constexpr 变量吗?
- 是否都是隐式内联的 constexpr 变量
- 为全局constexpr变量生成唯一值
- 错误!Constexpr变量必须通过常数表达式constexpr初始化
- 为什么我不能使用 msvc 在模板类中声明静态 constexpr 变量?
- 如果Constexpr - clang vs.GCC,则非constexpr变量
- Clang 在编译时不会计算非 constexpr 变量的 constexpr 函数的值