是否有可能在C 11中写出(S,f)或hasfield(S,f)的宏存在?

是否有可能在C 11中写出(S,f)或hasfield(S,f)的宏存在?,第1张

概述我对标准的元编程解决方案(例如 C++11 ways of finding if a type has member function or supports operator?)非常熟悉,它不涉及宏观魔法.但是,我有一个涉及以下便利宏的用例(当然,对于StackOverflow大大简化了,但想象这是用于序列化的东西)…… #define START(type) do { typedef type 我对标准的元编程解决方案(例如 C++11 ways of finding if a type has member function or supports operator?)非常熟悉,它不涉及宏观魔法.但是,我有一个涉及以下便利宏的用例(当然,对于StackOverflow大大简化了,但想象这是用于序列化的东西)……
#define START(type) do { typedef type current; const char typename[] = #type#define OUTPUT(fIEldname) \    printf("type of %s.%s is %s\n",#type,#fIEldname,\        std::is_same<decltype(std::declval<current>().fIEldname),int> ? "int" : "string")#define END() } while (0)struct Foo { int i; char *j; char *k; };struct bar { char *x; int y; };START(Foo);  OUTPUT(i);  // type of Foo.i is int  OUTPUT(j);  // type of Foo.j is string  OUTPUT(k);  // type of Foo.k is stringEND();START(bar);  OUTPUT(x);  // type of bar.x is string  OUTPUT(y);  // type of bar.y is intEND();

但现在让我们说有人出现并为我们的架构添加了一种新的数据成员:字段对(x,xLength).我们想要像这样改变我们的便利宏……

#define START(obj) do { const auto& current = (obj)#define OUTPUT(fIEldname) \    printf("type of %s.%s is %s\n",int> ? "int" :        hasfIEld(current,fIEldname##Length) ? "Pascal string" : "C string")#define END() } while (0)struct Baz { char *x,*y,*z; int xLength,zLength; };START(Baz);  OUTPUT(x);  // type of Baz.x is Pascal string  OUTPUT(y);  // type of Baz.y is C string  OUTPUT(z);  // type of Baz.z is Pascal stringEND();

就我自己而言,我设法提出了以下适用于Clang的hasfIEld实现…

#define hasfIEld(classtype,fIEldname)                                        \    []() {                                                                    \        struct X {                                                            \            template<class T,int=sizeof(&T::fIEldname)> static constexpr bool f(T*){ return true; } \            static constexpr bool f(...) { return false; }                    \        }; return X::f((classtype*)0);                                        \    }()

……但不幸的是,这似乎是由于a bug in Clang;根据C 11标准,本地类X不允许具有模板成员.实际上,这段代码无法与GCC一起编译.

所以我很难过:在C 11中是否有可能定义OUTPUT宏以便它能做我想做的事情?

绝对约束:不改变Baz的结构定义.没有提前对字段名进行硬编码.

Nice-to-haves:一个hasfIEld(c,f)宏,也可以在其他上下文中使用(而不是将代码直接缠绕到OUTPUT宏中).假设offsetof(c,fLength)== offsetof(c,f)sizeof(std :: declval< c>().f).

解决方法 通过继承当前和依赖阴影,可以使用一些可能或可能不重要的限制:声明一个本地fIEldname变量,创建一个从你正在检查的类型派生的本地类,并在成员函数,检查fIEldname是否仍然引用局部变量.如果是,则不存在成员字段名.
#include <utility>#include <stdio.h>#define START(type) do { typedef type current; const char typename[] = #type#define HASMEMBER(fIEldname) \    []() -> bool { \        struct HASMEMBER1 { } fIEldname; \        struct HASMEMBER2 : current { \             static char TEST1(HASMEMBER1&); \             static char (&TEST1(...))[2]; \             auto TEST2() -> decltype(TEST1(fIEldname)); \        }; \        return sizeof(std::declval<HASMEMBER2>().TEST2()) == 2; \    }()#define OUTPUT(fIEldname) \    printf("type of %s.%s is %s\n",typename,\        std::is_same<decltype(current::fIEldname),int>::value ? "int" : \        HASMEMBER(fIEldname##Length) ? "Pascal string" : "C string")#define END() } while (0)struct Foo { int i; char *j; char *k; };struct bar { char *x; int y; };struct Baz { char *x,zLength; };int main(){START(Foo);  OUTPUT(i);  // type of Foo.i is int  OUTPUT(j);  // type of Foo.j is C string  OUTPUT(k);  // type of Foo.k is C stringEND();START(bar);  OUTPUT(x);  // type of bar.x is C string  OUTPUT(y);  // type of bar.y is intEND();START(Baz);  OUTPUT(x);  // type of Baz.x is Pascal string  OUTPUT(y);  // type of Baz.y is C string  OUTPUT(z);  // type of Baz.z is Pascal stringEND();}

编辑参加GCC 4.6.3.它仍然被GCC 4.8.1和clang 3.3接受,并且也应该与GCC 4.7.3一起使用(但不是4.7.2).

总结

以上是内存溢出为你收集整理的是否有可能在C 11中写出(S,f)或hasfield(S,f)的宏存在?全部内容,希望文章能够帮你解决是否有可能在C 11中写出(S,f)或hasfield(S,f)的宏存在?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1240740.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存