C ++宏函数或动态成员名称

时间:2017-05-16 18:42:50

标签: c++ c++11 macros

我有以下结构:

struct myHandler
{
  bool test1;
  bool test2;
  ...
  bool test400;
};

其中有大约400个测试值。所以目前我有以下功能:

static inline void DoSomething(myHandler& hdler, int test, bool passed)
{
  #define SETTEST(a,b,c) case b: a.test##b=c;

  switch (test)
  {
    SETTEST(hdler, 1, passed)
    SETTEST(hdler, 2, passed)
    ...
    SETTEST(hdler, 400, passed)
  }

  #undef SETTEST
};

我显然试图摆脱重复的代码,因为有很多测试。所以我尝试了以下两个选项: 选项1:

static inline void DoSomething(myHandler& hdler, int test, bool passed)
{
  #define SETTEST(a,b,index,c) if(index==b) a.test##b=c;

  for(i = 1; i <= 400; ++i)
  {
    SETTEST(hdler, test, i, passed)
  }

  #undef SETTEST
};

显然这不会编译,因为当它使用##进行连接时需要&#34; test&#34;从字面上。不知道如何或者我是否可以解决这个问题。

选项2:

template<typename FUNCTION>
inline void setTest(FUNCTION f) {
  for (int i = 1; i <= 5; ++i) {
    f(i);
  }
};

static inline void DoSomething(myHandler& hdler, int test, bool passed
{
  setTest([&](const int testNum) { 
    if(test == testNum) {
      hdler.test##testNum = passed;
    }
  });
};

显然,option2也不会编译,我不知道如何使用某种动态形式访问结构的成员。现在,实际的结构有一些变化可以很容易地解决这个问题,但是修改结构不是一个选项,因为它是通过其他方法形成的,而这只是描述我的问题的示例代码。我只是想知道是否有办法做我想要实现的目标(不修改结构)我错过了。我真的倾向于选项2,但是根据我的阅读,没有办法动态连接以访问成员。任何帮助表示赞赏。

4 个答案:

答案 0 :(得分:3)

为什么不这样做:

struct myHandler {
   bool test[400] = {};
};

PS。不,你要做的事情是不可能的,因为你正试图混合代码预处理或编译时间和执行时间。有些人可能会考虑递归模板,但同样,你不能出于同样的原因这样做,因为你不能在模板中这样做。

您可以通过char *访问struct的最佳(也是最差)努力。任何代码审查员都会从你的头骨上制作一个葡萄酒高脚杯。 具体来说,这是一种反模式(通常):

myHandler s {};
unsigned char* p = reinterpret_cast<unsigned char*>(&s);

int index_value = 200;
int n = 0;
// sets index_value-th element to true.
std::generate(p, p+sizeof(s), [&n,=](){ return (++n)==index_value; })
//                    your "array" starts with 1^^^        

如果bool不等于char,或者如果你需要更大的类型,那将会有点花哨。 generate仅增加1。但是你可以通过任何可能的方式迭代数组。

答案 1 :(得分:3)

提升PP再次闪耀。

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>

#define SET_TEST(z, n, data) \
    case n: hdler.BOOST_PP_CAT(test, n) = passed; break;
//             Note : was the break missing here? ^^^^^^

switch (test)
{
    BOOST_PP_REPEAT_FROM_TO(1, 400, SET_TEST, ~)
}

#undef SET_TEST

哦 - 你需要一个Boost.PP的自定义版本,所以它最多可以达到400而不是默认的256:)

不认真......如果可以,请使用数组。

答案 2 :(得分:0)

您无法编写几行代码来访问结构的各个成员。

宏和模板将在编译时解析,因此您无法编写在运行时访问成员的类宏函数。

所以,如果你真的坚持使用类似这样的结构,你必须编写一个可以隐藏结构相当难看的性质的包装器。编写包装器仍然需要很多行,但一旦完成,代码的其他部分将更加简单。

它可能看起来像:

#include <iostream>
#include <array>
using namespace std;

struct myHandler
{
  bool test1;
  bool test2;
  // ..
  bool test400;
};

struct myHandlerWrapper
{
    myHandlerWrapper(myHandler& mh)
    {
        h[0] = &mh.test1;
        h[1] = &mh.test2;
            // .. 
        h[399] = &mh.test400;
    }

    bool& operator[](size_t i)  // This gives the easy access to members using simple indexing
    {
        return *h[i];
    }

    private:
    array<bool*, 400> h;
};

int main() {
    myHandler mh;
    myHandlerWrapper handler(mh);

    handler[0] = false;  // Access members using simple indexing via the wrapper
    handler[1] = true;

    cout << (handler[0] ? "true" : "false") << endl;
    cout << (handler[1] ? "true" : "false") << endl;

    return 0;
}

答案 3 :(得分:0)

我不认为这里有一个简单的问题解决方案,但您可以尝试最佳答案here

它讨论了是否可以迭代结构的成员(在C ++中不可能),并提供使用Boost的替代方案,如果这是一个选项,您。