我开始使用c ++ 11,constexpr和模板元编程似乎是一种在微型微控制器上保存稀缺内存的好方法.
有没有办法编写模板来展平constexpr数组列表,我需要的是一种方法:
constexpr std::array<int, 3> a1 = {1,2,3};
constexpr std::array<int, 2> a2 = {4,5};
constexpr auto a3 = make_flattened_array (a1,a2);
Run Code Online (Sandbox Code Playgroud)
我使用gcc 4.8.4(arm-none-eabi),如果需要,可以使用std = c ++ 11或c ++ 1y选项进行编译.
例如:
constexpr int g() { return 30; }
constexpr int f()
{
// Can we omit const?
const int x = g();
const int y = 10;
return x + y;
}
Run Code Online (Sandbox Code Playgroud)
有没有必要在constexpr函数中声明局部变量const?
局部变量的constexpr函数不等于没有const局部变量的函数吗?const
换句话说,constexpr函数是否强加(暗示)const它的局部变量?
"第一次尝试"不会编译,而第二次尝试则不会编译.为什么?有什么不同?
第一次尝试:
#include <iostream>
int main()
{
constexpr const char text2[] = "hello";
constexpr const char * b = &text2[4]; // error: '& text2[4]' is not a constant expression
std::cout << b << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
第二次尝试:
#include <iostream>
int main()
{
constexpr const char * text1 = "hello";
constexpr const char * a = &text1[4];
std::cout << a << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我编译(g ++版本4.9.2)
g++ -std=c++11 -o main *.cpp
Run Code Online (Sandbox Code Playgroud)
这给出了以下错误
main.cpp: In function 'int main()':
main.cpp:7:40: error: '& text2[4]' …Run Code Online (Sandbox Code Playgroud) 考虑:
#include <compare>
template<class=void>
constexpr int f() { return 1; }
unsigned int x;
using T = decltype(x <=> f());
Run Code Online (Sandbox Code Playgroud)
GCC 和 MSVC 接受T. Clang 拒绝了它,并显示以下错误消息:
Run Code Online (Sandbox Code Playgroud)<source>:7:26: error: argument to 'operator<=>' cannot be narrowed from type 'int' to 'unsigned int' using T = decltype(x <=> f()); ^ 1 error generated.
(现场演示)
如果模板头 ( template<class=void>) 被移除,或者如果f在 的声明之前显式或隐式实例化T,则 Clang 接受它。例如,Clang 接受:
#include <compare>
template<class=void>
constexpr int f() { return 1; }
unsigned x; …Run Code Online (Sandbox Code Playgroud) 我在尝试翻转号码的所有位时遇到了一个奇怪的问题。
#include <cstdint>
constexpr uint16_t DefaultValueForPortStatus { 0xFFFF };
void f(uint16_t x)
{
}
int main()
{
f(~(DefaultValueForPortStatus));
}
Run Code Online (Sandbox Code Playgroud)
当我编译这个程序(GCC trunk)时,我收到一个错误:
警告:从“int”到“uint16_t”的无符号转换{aka“short unsigned int”}将值从“-65536”更改为“0”[-Woverflow]
当我从类型说明符中删除 constexpr 时,不会出现警告。这是为什么?为什么编译器将 uint16_t constexpr 变量更改为 int,而在非 constexpr 的情况下一切都很好?
我在使用 g++-12 时遇到错误,但在 clang++-13 中不会发生该错误。特别是,这段代码:
\nstruct A {\n constexpr virtual ~A() = default;\n constexpr A() = default;\n};\n\nstruct B : public A {\n constexpr ~B() = default;\n constexpr B() = default;\n};\n\nconstexpr int demo(){\n B *b = new B();\n delete b;\n return 2;\n}\n\nint main(){\n constexpr int demod = demo();\n return demod;\n}\nRun Code Online (Sandbox Code Playgroud)\n使用 clang++ 编译,但使用 g++ 编译会出现错误:
\nstruct A {\n constexpr virtual ~A() = default;\n constexpr A() = default;\n};\n\nstruct B : public A {\n constexpr ~B() = default;\n constexpr B() …Run Code Online (Sandbox Code Playgroud) 我正在编译时使用计算一些数据std::vector,并希望将结果作为数组返回,以便可以在运行时进一步使用。我在不进行两次计算的情况下设置数组大小时遇到问题。
这是我迄今为止所做的事情的简化示例。代码按预期编译并运行。
constexpr auto make_vector() {
// complex calculation here
return std::vector{1, 2, 3};
}
constexpr auto make_array() {
const auto vec = make_vector();
std::array<int, make_vector().size()> result{};
std::copy(vec.cbegin(), vec.cend(), result.begin());
return result;
}
int main() {
constexpr auto result = make_array(); // std::array<int, 3>{1, 2, 3}
}
Run Code Online (Sandbox Code Playgroud)
我理解为什么不能用于vec.size()数组大小以及为什么make_vector().size()会产生编译时常量。做两次似乎不是正确的方法。
有没有办法避免调用make_vector两次?我在这里错过了一个基本概念吗?
我遇到以下代码时遇到问题:
template<typename T>
constexpr int get(T vec) {
return vec.get();
}
struct coord {
constexpr int get() const { return x; }
int x;
};
struct foo {
struct coord2 {
constexpr int get() const { return x; }
int x;
};
constexpr static coord f = { 5 };
constexpr static int g = get(f); // works
constexpr static coord2 h = { 5 };
constexpr static int i = get(h); // doesn't work
};
constexpr coord foo::f;
constexpr …Run Code Online (Sandbox Code Playgroud) 我有一个模板类C,它具有类型的非类型但引用模板参数P:
class P {
public:
int x;
int y;
};
template <const P &x>
class C {
public:
const int &f() { return x.x; }
};
Run Code Online (Sandbox Code Playgroud)
我声明了一个类型的全局变量P:
P p = {33,44};
Run Code Online (Sandbox Code Playgroud)
我还声明了一个返回引用的函数p:
constexpr const P &h() { return p; }
Run Code Online (Sandbox Code Playgroud)
然后尝试在下面使用这些:
C<p> o; // line 1
C<h()> oo; // line 2
Run Code Online (Sandbox Code Playgroud)
当然我对第一次实例化没有问题,但第二次实例化没有问题.我的编译器抱怨:
error: non-type template argument does not refer to any declaration
Run Code Online (Sandbox Code Playgroud)
为什么会这样?我无法在常规中找到反对它的论据.我不确定它是否与在默认模板参数中调用constexpr完全相同的问题,其中讨论是关于嵌套 instanciation的实例化点.这是一个类型问题,但哪一个?我的函数h()返回对定义良好的类型(const …
C++标准特别禁止调用new常量表达式(N4296第5.20节[expr.const]):
条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:
...
- 一个新表达式(5.3.4);
这项禁令(据我所知)延伸到所有形式new,包括新的安置.但是,由于placement new实际上并没有分配任何内存,只是在给定位置运行构造函数,并且因为在constexpr上下文中获取变量的地址是合法的(事实上,std::addressof在C++ 17中将是constexpr),似乎对我来说,这个禁令(原则上至少)可以放宽,以允许在constexpr功能中放置新的禁令.
所以我的问题是,我错过了什么吗?有没有一个很好的理由为什么在constexpr功能中禁止放置新的?
(对于上下文:当前规则几乎要求启用constexpr的sum类型std::variant实现为递归联合.能够使用类似std::aligned_storage和贴片new的东西会更好,但目前这是不可能的.)