是否可以使用C++ 11 使用构造函数initializer_list组装递归定义的类Foo,如下所示constexpr:
template <size_t N>
struct Foo {
constexpr Foo(int x, Foo<N-1> f) : x(x), xs(xs) {}
int x;
Foo<N-1> xs;
};
template <> struct Foo<0> {};
Run Code Online (Sandbox Code Playgroud)
我可以初始化一个Foo<3>使用:
int main(int argc, char *argv[])
{
Foo<3> a = Foo<3>(1,Foo<2>(2,Foo<1>(3,Foo<0>())));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
最好使用Foo <3> a = {1,2,3}.如果有一个constexpr tail功能,initializer_list我认为它应该工作.
c++ recursive-datastructures initializer-list constexpr c++11
假设我想在编译时使用某种算法构建图形,然后计算图形中结束的节点数.这似乎是constexpr的理想情况,而不是模板元编程,因为目标是计算产生一个值,而不是真正的类型.我有一些有用的代码,但功能是如此新,我担心编译器是宽松的,我可以解释部分标准说我不能这样做.
#include <iostream>
struct A { int x; constexpr A(int i) noexcept : x{i} {} };
struct B { A& a; constexpr B(A& a) noexcept : a{a} {} };
constexpr int foo() {
A a{55};
B b{a};
return b.a.x;
}
template<int N>
void output()
{
std::cout << N << std::endl;
}
int main() {
// to be absolutely sure compile time eval'd,
// pass as template arg
constexpr auto b = foo();
output<b>();
}
Run Code Online (Sandbox Code Playgroud)
这两个a和b实例都是在编译时创建的,它们具有相同的生命周期,所以这应该是"安全的".但这a …
使用clang(版本3.0-6ubuntu3)编译此代码时:
constexpr int foo(const int n) {
return n + 1;
}
int main(void) {
constexpr int x = 5 * 4 + 12 + 8;
constexpr int y = foo(x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用此命令:
clang -std=c++11 -c constexprExample.cpp
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
错误:constexpr变量'y'必须由常量表达式初始化
代码或编译器有问题吗?
简而言之,这是一个最小的例子:
struct C {
const int X = 2;
int y = 2;
};
void f(C* x) {
switch(x->y) {
case x->X: printf("%d", 42); break;
case 123: printf("foo");
}
}
int main()
{
C c;
f(&c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器会抱怨error: 'x' is not a constant expression以及如何修复它?
我试图装饰时遇到错误consexpr:
$ g++ -std=c++11 test.cxx -o test.exe
test.cxx: In instantiation of ‘static constexpr unsigned int MinMaxStep<min, max
, step>::ValidValue(unsigned int) [with unsigned int min = 10u; unsigned int max
= 100u; unsigned int step = 10u]’:
test.cxx:22:40: required from here
test.cxx:16:5: error: body of constexpr function ‘static constexpr unsigned int
MinMaxStep<min, max, step>::ValidValue(unsigned int) [with unsigned int min = 10
u; unsigned int max = 100u; unsigned int step = 10u]’ not a return-statement
}
^
Run Code Online (Sandbox Code Playgroud)
问题函数中使用的所有值都是模板参数.保存文件后,值不会更改.
难道不能将其表达为一种 …
想知道以下是否让任何人感到惊讶,就像它对我一样?Alex Allain 在这里使用constexpr 的文章显示了以下因子示例:
constexpr factorial (int n)
{
return n > 0 ? n * factorial( n - 1 ) : 1;
}
Run Code Online (Sandbox Code Playgroud)
并指出:
现在你可以使用factorial(2),当编译器看到它时,它可以优化掉调用并在编译时完全进行计算.
我在VS2015中以释放模式尝试了这一点,并对(/ Ox)进行了全面优化,并逐步查看调试器中查看程序集的代码,并看到在编译时没有进行因子计算.
使用GCC v5.4.0和--std = C++ 14,我必须在编译时执行计算之前使用/ O2或/ O3.我很惊讶,在编译时没有使用/ O计算.
主要问题是:为什么VS2015在编译时没有执行此计算?
我正在考虑使用当前时间戳作为一个版本.我想在编译时检索该信息.理想情况下,我想这样做:
constexpr long long currentTimestamp = getCurrentTimestamp();
Run Code Online (Sandbox Code Playgroud)
这可能与C++ 14有关吗?
有没有一种方法可以在编译时为字符串或加密的字符串创建哈希值?我想将生成加密文本或哈希值的原始字符串直接作为字符串文字放入我的代码中,但是我不希望它们以未转换的形式被编译成可执行文件。
像这样吗
constexpr uint32 hash(const char * string){
... // turns a string into a value to represent it
}
constexpr std::string encrypt(const char * string){
... // turns a string into a cyphertext (unsure what return type would work best here)
}
void f(){
std::string input << std::cin();
switch(hashedKey){
case hash("help"): // legal?
if(0 == encryptRT(input).compare(encrypt("secret string")){
// the secret string should never appear in the executable
}
break;
}
}
Run Code Online (Sandbox Code Playgroud)
非常重要的一点是,直接放入constexpr函数中的字符串切勿放入字符串表中。这可能吗?
要为编译时递归定义模板,我要定义2个模板,一个普通模板,另一个用于"初始"情况,如下所示:
template<int i>
struct Int {};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i>
constexpr auto iter(Int<i>) -> decltype(auto) {
return iter(Int<i-1>{});
}
int main() {
decltype(iter(Int<10>{})) a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是gcc发出警告:
warning: inline function 'constexpr Int<0> iter(Int<0>)' used but never defined
constexpr auto iter(Int<0>) -> Int<0>;
Run Code Online (Sandbox Code Playgroud)
为什么会出现这样的警告?
我正在尝试将一个int作为参数并单独对其字节进行操作,例如,采用0xDEADF00D并一一处理每个字节:0xDE 0xAD 0xF0 0x0D
为此,我完成了以下代码:
template <int state, int seed>
constexpr static uint32_t CalculateRandomFromState()
{
const char bytes[4] = {
(state >> 24) & 0xFF,
(state >> 16) & 0xFF,
(state >> 8) & 0xFF,
state & 0xFF,
};
constexpr auto value = Compiletime::Hash<seed, sizeof(bytes)>(bytes);
return value;
}
Run Code Online (Sandbox Code Playgroud)
HashFn的信号为:
template <const uint32_t seed, const uint32_t size = NULL>
constexpr uint32_t Hash(const char* message)
Run Code Online (Sandbox Code Playgroud)
编译因以下原因而失败:
错误C2131:表达式未求值为常数
注意:失败是由于在其生命周期之外读取变量导致的
注意:请参阅“字节”的用法
我已经在StackOverflow上阅读了有关参数可能无法在编译时进行评估的主题,(这就是为什么我将大多数参数切换为模板变量的原因,因此100%确保了它们在编译时),但是在这种情况下,它不会为何给出错误似乎是合乎逻辑的。该bytes值取决于编译时间值,字节也是一个常数。
为什么会超出使用寿命?如果我说"somestring"而不是变量,bytes那么它可以完美编译。这里有什么不可以持续评估的?