Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有条件地初始化结构字段-仅当该结构中存在该字段时_C++_Api_Unit Testing_Reflection_Initialization - Fatal编程技术网

C++ 有条件地初始化结构字段-仅当该结构中存在该字段时

C++ 有条件地初始化结构字段-仅当该结构中存在该字段时,c++,api,unit-testing,reflection,initialization,C++,Api,Unit Testing,Reflection,Initialization,为一个非常简单的API开发类似于单元测试框架的东西: extern "C" void execute_command(int cmd, void *params); 它根据cmd参数将params强制转换为相应的结构。我不能更改该接口,也不能修改指定命令和不同参数结构(都是POD)的标题 我确实可以访问以下内容的数组: { 0 /*cmd number*/, "PARAM_STRUCT_FOR_CMD_0", sizeof(PARAM_STRUCT_FOR_CMD_0) } void *pG

为一个非常简单的API开发类似于单元测试框架的东西:

extern "C" void execute_command(int cmd, void *params);
它根据
cmd
参数将
params
强制转换为相应的结构。我不能更改该接口,也不能修改指定命令和不同参数结构(都是POD)的标题

我确实可以访问以下内容的数组:

{ 0 /*cmd number*/, "PARAM_STRUCT_FOR_CMD_0", sizeof(PARAM_STRUCT_FOR_CMD_0) }
void *pGlobalObject;
void execcmd(int cmd)
{
    static uint8_t params[MAX_SIZE_OF_PARAM_STRUCT];

    memset(params, 0, MAX_SIZE_OF_PARAM_STRUCT);
    INIT_STRUCT_IF_POSSIBLE(cmd, (void*)params);
    execute_command(cmd, params);
}
#define INIT_STRUCT_IF_POSSIBLE(cmd, str) \
do {  \
    switch (cmd)  \
    {  \
        case 0: static_cast<PARAM_STRUCT_FOR_CMD_0*>(str)->pObject = pGlobalObject; break;  \
        case 1: static_cast<PARAM_STRUCT_FOR_CMD_1*>(str)->pObject = pGlobalObject; break;  \
        case 2: /* nothing, no pObject field */ break;  \
    }  \
} while (0)
这些参数结构具有一些公共属性。例如,它们中的许多具有类似
void*pObject的字段,但它并不总是相同的偏移量。为了进行说明,假设有三种结构:

struct {
    void *pObject;
    int someData;
} PARAM_STRUCT_FOR_CMD_0;
struct {
    float someFloatData;
    void *pObject;
} PARAM_STRUCT_FOR_CMD_1;
struct {
    float someFloatData;
    void *pAnotherObject;
} PARAM_STRUCT_FOR_CMD_2;
这两个
pObject
字段表示相同的对象,而
pAnotherObject
则不相关

现在,我想根据
cmd
void*
强制转换为某个结构,并设置其
pObject
字段(如果该结构中存在)。理想情况下,我可以做以下事情:

{ 0 /*cmd number*/, "PARAM_STRUCT_FOR_CMD_0", sizeof(PARAM_STRUCT_FOR_CMD_0) }
void *pGlobalObject;
void execcmd(int cmd)
{
    static uint8_t params[MAX_SIZE_OF_PARAM_STRUCT];

    memset(params, 0, MAX_SIZE_OF_PARAM_STRUCT);
    INIT_STRUCT_IF_POSSIBLE(cmd, (void*)params);
    execute_command(cmd, params);
}
#define INIT_STRUCT_IF_POSSIBLE(cmd, str) \
do {  \
    switch (cmd)  \
    {  \
        case 0: static_cast<PARAM_STRUCT_FOR_CMD_0*>(str)->pObject = pGlobalObject; break;  \
        case 1: static_cast<PARAM_STRUCT_FOR_CMD_1*>(str)->pObject = pGlobalObject; break;  \
        case 2: /* nothing, no pObject field */ break;  \
    }  \
} while (0)
其中,
INIT\u STRUCT\u如果可能的话
可以是:

{ 0 /*cmd number*/, "PARAM_STRUCT_FOR_CMD_0", sizeof(PARAM_STRUCT_FOR_CMD_0) }
void *pGlobalObject;
void execcmd(int cmd)
{
    static uint8_t params[MAX_SIZE_OF_PARAM_STRUCT];

    memset(params, 0, MAX_SIZE_OF_PARAM_STRUCT);
    INIT_STRUCT_IF_POSSIBLE(cmd, (void*)params);
    execute_command(cmd, params);
}
#define INIT_STRUCT_IF_POSSIBLE(cmd, str) \
do {  \
    switch (cmd)  \
    {  \
        case 0: static_cast<PARAM_STRUCT_FOR_CMD_0*>(str)->pObject = pGlobalObject; break;  \
        case 1: static_cast<PARAM_STRUCT_FOR_CMD_1*>(str)->pObject = pGlobalObject; break;  \
        case 2: /* nothing, no pObject field */ break;  \
    }  \
} while (0)
#如果可能,定义初始化结构(cmd,str)\
做{\
开关(cmd)\
{  \
案例0:static_cast(str)->pObject=pGlobalObject;break\
案例1:static_cast(str)->pObject=pGlobalObject;break\
情况2:/*无,无对象字段*/中断\
}  \
}而(0)
但这并不是真正的可伸缩性。我有大约1000个可能的命令,比如说我想设置的5个字段(没有任何结构都有5个),并且可以添加新命令,所以我希望避免手动更改

显而易见的解决方案是一个额外的构建步骤,它解析所有结构,并创建它们的初始值设定项。由于这个项目是如何结构化的,添加这个额外的构建步骤是很痛苦的,所以我希望有一个纯粹的C++解决方案。 如果有办法使用C预处理器生成初始值设定项,我完全赞成。如果它可以用模板来完成,也一样好。如果有帮助的话,我有boost和C++11


解决这个问题的一个方法是指定初始值设定项,例如
strx={.pObject=pGlobalObject;}。不幸的是,当字段不可用时,它们会导致错误。有没有办法忽略不存在的字段?(是的,我知道它们是C,而不是C++,但是如果需要,我可以切换到C)

#include <iostream>
#include <type_traits>

// Member variable detection
// =========================

template<typename T, typename = void>
struct has_pObject : std::false_type { };

template<typename T>
struct has_pObject<T, decltype(std::declval<T>().pObject, void())> : std::true_type { };

// Optional member variable assignment
// ===================================

namespace Detail
{
    template <typename T>
    void assign_pObject(T& object, void* p, std::false_type) {}

    template <typename T>
    void assign_pObject(T& object, void* p, std::true_type) {
        object.pObject = p;
    }
}

template <typename T>
void assign_pObject(T& object, void* p) {
    Detail::assign_pObject(object, p, has_pObject<T>());
}

// Test
// ====

struct {
    void *pObject = nullptr;
    int someData = 0;
} PARAM_STRUCT_FOR_CMD_0;

struct {
    float someFloatData = 0;
    void *pObject = nullptr;
} PARAM_STRUCT_FOR_CMD_1;

struct {
    float someFloatData = 0;
    void *pAnotherObject = nullptr;
} PARAM_STRUCT_FOR_CMD_2;

int main()
{
    int object;
    assign_pObject(PARAM_STRUCT_FOR_CMD_0, &object);
    assign_pObject(PARAM_STRUCT_FOR_CMD_1, &object);
    assign_pObject(PARAM_STRUCT_FOR_CMD_2, &object);
    std::cout << PARAM_STRUCT_FOR_CMD_0.pObject << '\n';
    std::cout << PARAM_STRUCT_FOR_CMD_1.pObject << '\n';
    std::cout << PARAM_STRUCT_FOR_CMD_2.pAnotherObject << '\n';
    return 0;
}
#包括
#包括
//成员变量检测
// =========================
模板
结构具有_pObject:std::false _type{};
模板
结构有_pObject:std::true_type{};
//可选成员变量赋值
// ===================================
名称空间详细信息
{
模板
void assign_pObject(T&object,void*p,std::false_type){}
模板
void assign\u pObject(T&object,void*p,std::true\u类型){
object.pObject=p;
}
}
模板
无效分配对象(T和对象,无效*p){
Detail::assign_pObject(对象,p,has_pObject());
}
//试验
// ====
结构{
void*pObject=nullptr;
int-someData=0;
}用于命令0的参数结构;
结构{
float someFloatData=0;
void*pObject=nullptr;
}用于命令1的参数结构;
结构{
float someFloatData=0;
void*pAnotherObject=nullptr;
}用于命令2的参数结构;
int main()
{
int对象;
分配对象(对象的参数结构);
分配对象(用于对象1和对象的参数结构);
分配对象(用于对象2和对象的参数结构);

std::cout使用某些SFINAE,您可以检测成员并相应地(键入)分派分配:

#include <iostream>
#include <type_traits>

// Member variable detection
// =========================

template<typename T, typename = void>
struct has_pObject : std::false_type { };

template<typename T>
struct has_pObject<T, decltype(std::declval<T>().pObject, void())> : std::true_type { };

// Optional member variable assignment
// ===================================

namespace Detail
{
    template <typename T>
    void assign_pObject(T& object, void* p, std::false_type) {}

    template <typename T>
    void assign_pObject(T& object, void* p, std::true_type) {
        object.pObject = p;
    }
}

template <typename T>
void assign_pObject(T& object, void* p) {
    Detail::assign_pObject(object, p, has_pObject<T>());
}

// Test
// ====

struct {
    void *pObject = nullptr;
    int someData = 0;
} PARAM_STRUCT_FOR_CMD_0;

struct {
    float someFloatData = 0;
    void *pObject = nullptr;
} PARAM_STRUCT_FOR_CMD_1;

struct {
    float someFloatData = 0;
    void *pAnotherObject = nullptr;
} PARAM_STRUCT_FOR_CMD_2;

int main()
{
    int object;
    assign_pObject(PARAM_STRUCT_FOR_CMD_0, &object);
    assign_pObject(PARAM_STRUCT_FOR_CMD_1, &object);
    assign_pObject(PARAM_STRUCT_FOR_CMD_2, &object);
    std::cout << PARAM_STRUCT_FOR_CMD_0.pObject << '\n';
    std::cout << PARAM_STRUCT_FOR_CMD_1.pObject << '\n';
    std::cout << PARAM_STRUCT_FOR_CMD_2.pAnotherObject << '\n';
    return 0;
}
#包括
#包括
//成员变量检测
// =========================
模板
结构具有_pObject:std::false _type{};
模板
结构有_pObject:std::true_type{};
//可选成员变量赋值
// ===================================
名称空间详细信息
{
模板
void assign_pObject(T&object,void*p,std::false_type){}
模板
void assign\u pObject(T&object,void*p,std::true\u类型){
object.pObject=p;
}
}
模板
无效分配对象(T和对象,无效*p){
Detail::assign_pObject(对象,p,has_pObject());
}
//试验
// ====
结构{
void*pObject=nullptr;
int-someData=0;
}用于命令0的参数结构;
结构{
float someFloatData=0;
void*pObject=nullptr;
}用于命令1的参数结构;
结构{
float someFloatData=0;
void*pAnotherObject=nullptr;
}用于命令2的参数结构;
int main()
{
int对象;
分配对象(对象的参数结构);
分配对象(用于对象1和对象的参数结构);
分配对象(用于对象2和对象的参数结构);

std::cout使用某些SFINAE,您可以检测成员并相应地(键入)分派分配:

#include <iostream>
#include <type_traits>

// Member variable detection
// =========================

template<typename T, typename = void>
struct has_pObject : std::false_type { };

template<typename T>
struct has_pObject<T, decltype(std::declval<T>().pObject, void())> : std::true_type { };

// Optional member variable assignment
// ===================================

namespace Detail
{
    template <typename T>
    void assign_pObject(T& object, void* p, std::false_type) {}

    template <typename T>
    void assign_pObject(T& object, void* p, std::true_type) {
        object.pObject = p;
    }
}

template <typename T>
void assign_pObject(T& object, void* p) {
    Detail::assign_pObject(object, p, has_pObject<T>());
}

// Test
// ====

struct {
    void *pObject = nullptr;
    int someData = 0;
} PARAM_STRUCT_FOR_CMD_0;

struct {
    float someFloatData = 0;
    void *pObject = nullptr;
} PARAM_STRUCT_FOR_CMD_1;

struct {
    float someFloatData = 0;
    void *pAnotherObject = nullptr;
} PARAM_STRUCT_FOR_CMD_2;

int main()
{
    int object;
    assign_pObject(PARAM_STRUCT_FOR_CMD_0, &object);
    assign_pObject(PARAM_STRUCT_FOR_CMD_1, &object);
    assign_pObject(PARAM_STRUCT_FOR_CMD_2, &object);
    std::cout << PARAM_STRUCT_FOR_CMD_0.pObject << '\n';
    std::cout << PARAM_STRUCT_FOR_CMD_1.pObject << '\n';
    std::cout << PARAM_STRUCT_FOR_CMD_2.pAnotherObject << '\n';
    return 0;
}
#包括
#包括
//成员变量检测
// =========================
模板
结构具有_pObject:std::false _type{};
模板
结构有_pObject:std::true_type{};
//可选成员变量赋值
// ===================================
名称空间详细信息
{
模板
void assign_pObject(T&object,void*p,std::false_type){}
模板
void assign\u pObject(T&object,void*p,std::true\u类型){
object.pObject=p;
}
}
模板
无效分配对象(T和对象,无效*p){
Detail::assign_pObject(对象,p,has_pObject());
}
//试验
// ====
结构{
void*pObject=nullptr;
int-someData=0;
}用于命令0的参数结构;
结构{
float someFloatData=0;
void*pObject=nullptr;
}用于命令1的参数结构;
结构{
float someFloatData=0;
void*pAnotherObject=nullptr;
}用于命令2的参数结构;
int main()
{
int对象;
分配对象(对象的参数结构);
分配对象(用于对象1和对象的参数结构);
分配对象(用于对象2和对象的参数结构);

std::cout使用某些SFINAE,您可以检测成员并相应地(键入)分派分配:<