我有一个以下结构:
struct Data
{
std::string firstMember;
std::string secondMember;
std::string thirdMember;
};
Run Code Online (Sandbox Code Playgroud)
我想按字符串名称选择其中一个成员constexpr,比如
Data instance;
auto& member = getMember(instance, "firstMember");
Run Code Online (Sandbox Code Playgroud)
getMember是constexpr函数/ struct/macros /有问题和表达式应该(我希望它)优化为简单auto& member = instance.firstMember;.我的愿望是能够getMember从另一个constexpr函数调用,而另一个函数又是特定成员的计算名称 - >某种编译时间反射.
我知道,C++中没有反射,因此可以以某种方式注册(部分特殊化?使用一些宏魔法?)有问题的struct成员名称,如:
REGISTER_MEMBER(Data, "firstMember", firstMember);
Run Code Online (Sandbox Code Playgroud)
我想要的只是编译时优化并在运行时不执行任何操作.这可能在C++ 11中如何实现?
在C++ 11中,我们得到constexpr:
constexpr int foo (int x) {
return x + 1;
}
Run Code Online (Sandbox Code Playgroud)
是否可以使用编译时错误foo的动态值进行调用x?也就是说,我想创建一个foo只能传递constexpr参数的东西.
我写了一个返回数组的constexpr函数.
#include <iostream>
constexpr auto get_str(void)
-> const char(&)[4] {
return { 'T', 'E', 'S', 'T' };
}
constexpr int sum(const char(&str)[4]){
return str[0] + str[1] + str[2] + str[3];
}
int main(void){
constexpr int s = sum(get_str());
std::cout << s << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
g ++ 4.8正确编译代码,但发出以下警告:
test.cpp: In function ‘constexpr const char (& get_str())[4]’:
test.cpp:5:30: warning: returning reference to temporary [-Wreturn-local-addr]
return { 'T', 'E', 'S', 'T' };
Run Code Online (Sandbox Code Playgroud)
在这种情况下警告是否正确?从这样的constexpr函数返回数组是不正确的,即使该函数在运行时从未实际调用过,只是在编译期间?
我有以下C++ 11代码(简化版):
struct Info
{
const char * name;
int version;
};
class Base
{
public:
const Info info;
Base (Info info) : info (info) {}
};
class Derived : public Base
{
public:
static constexpr Info info = {"Foobar", 2};
Derived () : Base (info) {}
};
int main ()
{
static Derived derived;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC 4.9.1编译并链接此代码.另一方面,Clang 3.5.0抱怨未定义的引用:
/tmp/test-109c5c.o: In function `main':
test.cc:(.text+0x1c): undefined reference to `Derived::info'
test.cc:(.text+0x22): undefined reference to `Derived::info'
clang: error: linker command failed …Run Code Online (Sandbox Code Playgroud) 我想根据参数选择在构造函数中初始化的union成员.以下是一个有效的示例:
struct A {
union {
int i;
float f;
};
A(double d, bool isint) {
if (isint) new(&i) int(d);
else new(&f) float(d);
}
};
Run Code Online (Sandbox Code Playgroud)
虽然我使用int和float,我们的目标是与其他更复杂的类型(但仍允许在C++ 14集),因此,使用位置,新的(不是分配)的工作.
问题是这个构造函数不能constexpr像constexpr方法那样不允许使用placement-new .有没有办法解决这个问题(除了使isint参数成为正式类型系统的一部分)?某种类型的条件初始化列表可以工作,但我不知道有办法做到这一点.
这里有一个类似的问题,但它没有有价值的信息,所以我想再问一遍 - 是否可以使用constexpr函数加载任意文件的内容?我知道这似乎是不可能的,因为在这种情况下无法调用允许文件I/O(fopen,open...)的所有可能的函数constexpr.但是 - 由于这里有许多人关注c ++ 17的开发并且正在进行 - 是否有希望进一步的标准将包含一些文件I/O API,它们将constexpr在编译时用于加载文件?
仅仅为了比较--Haxe允许通过编译时宏执行几乎任何操作,因此在C++中使用类似的东西会非常酷.例如,通过反序列化文件生成类实例.
在嵌入式编程中,您经常需要设置指向物理地址的指针.该地址不可重定位并已修复.这些不是由链接器设置的,因为它们通常代表寄存器或在这种情况下位于OPT存储器中预定地址的校准数据.当芯片制造商首次在生产中测试器件时,设置该数据.
所以第一次尝试是:
static constexpr uint16_t *T30_CAL = reinterpret_cast<uint16_t *>(0x1FFFF7B8u);
Run Code Online (Sandbox Code Playgroud)
但这导致GCC下面的警告/错误,并且根据标准(c ++ 14)是"非法的".
..xyz/xxxx/calibration.cpp:23:40:错误:从整数到指针的reinterpret_cast
现在我可以捏造它
constexpr uint32_t T30_ADDR = 0x1FFFF7B8u;
static constexpr inline uint16_t *T30_CAL(){
return reinterpret_cast<uint16_t *>(T30_ADDR);
}
Run Code Online (Sandbox Code Playgroud)
编译没有警告,但......
我想GCC可以选择将其编译为函数而不是constexpr,尽管它每次都会内联这个函数.
这样做有更简单,更符合标准的方法吗?
对于嵌入式代码,这些定义始终是必需的,因此如果有一种不需要函数定义的简单方法,那就太好了.
对前面问题的回答通常会得出一个答案,说明标准中不允许这样做,并将其留在那里.
这不是我想要的.我需要一种使用C++生成编译时常量指针到固定地址的兼容方式.我想在不使用Macros的情况下这样做,因为我的代码会使用强制转换器导致问题导致问题.这导致需要在多个地方而不是一个地方获得合规性例外.每个例外都是一个过程,需要时间和精力.
Constexpr在嵌入式系统上保证常量放在.text段(flash)中,而const则不放置.text段(flash).它可以放在有价值的ram中,并由.bss启动代码初始化.通常,嵌入式设备具有比RAM更多的闪存.此外,访问RAM中变量的代码通常效率低得多,因为它通常涉及嵌入式目标(如ARM)上至少两次内存访问.一个用于加载变量的RAM地址,另一个用于从变量的位置加载实际的常量指针值.Constexpr导致常量指针直接编码到指令流中或导致单个恒定负载.
如果这只是一个单独的实例,那就不是问题了,但是你通常有很多不同的外设,每个都通过自己的寄存器组进行控制,然后这就成了问题.
许多嵌入式代码最终会读写外设寄存器.
我得到的最小例子有点复杂:
struct A { };
template <int>
struct Parent { };
template <int N>
constexpr int operator*(A, Parent<N>*) { return N; }
template <class T>
using ptr = T*;
template <int>
struct Other { };
template <int N>
struct Kid: Parent<N> {
static Other<A{} * ptr<Kid>{}> o;
};
int main() {
Kid<2>{};
}
Run Code Online (Sandbox Code Playgroud)
[GCC]编译代码而没有任何问题,[铛]抱怨匹配Parent针对Kid问题:
prog.cc:7:15: note: candidate template ignored: could not match 'Parent' against 'Kid'
constexpr int operator*(A, Parent<N>*) { return N; } …Run Code Online (Sandbox Code Playgroud) c++ language-lawyer incomplete-type constexpr template-argument-deduction
所以我需要一些log10功能来查找存储给定整数所需的字符数.但是我想在编译时得到它来根据我的代码中定义的这些整数常量静态地确定char数组的长度.不幸的log10是,它不是一个constexpr函数,即使是整数版本.我可以制作这样的完整版本:
template <typename T>
constexpr enable_if_t<is_integral_v<T>, size_t> intlen(T param) {
size_t result{ 1U };
while(T{} != (param /= T{ 10 })) ++result;
return result;
}
Run Code Online (Sandbox Code Playgroud)
这将最终允许我这样做:c ++const char foo[intlen(13) + 1U]
是否已经为我提供了一个工具,还是我必须自己定义?
请考虑以下代码:
template <int N, typename T> void f(T) { }
template <typename T>
constexpr int k(T&) { return 0; }
int main()
{
constexpr auto i = 1;
f<k(i)>([&i]
{
f<k(i)>(0);
});
}
Run Code Online (Sandbox Code Playgroud)
clang++ (主干)编译它.g++ (trunk)因以下错误而失败:
Run Code Online (Sandbox Code Playgroud)<source>: In lambda function: <source>:11:19: error: no matching function for call to 'f<k<const int>((* & i))>(int)' 11 | f<k(i)>(0); | ^ <source>:1:35: note: candidate: 'template<int N, class T> void f(T)' 1 | template <int N, typename T> void f(T) { } …