C++ 直接访问唯一类数据成员

C++ 直接访问唯一类数据成员,c++,c++11,templates,memory-address,C++,C++11,Templates,Memory Address,我有一个具有唯一公共数据成员的类,该成员是内置类型: class foo { public: int data; foo(int dataIn) : data(dataIn) {} virtual ~foo() {} // Some other class methods protected: // Some internal helper class methods }; 在另一个类中,我想使用memcpy方法: template<typen

我有一个具有唯一公共数据成员的类,该成员是内置类型:

class foo {
public:
    int data;

    foo(int dataIn) : data(dataIn) {}
    virtual ~foo() {}

    // Some other class methods
protected:
    // Some internal helper class methods
};
在另一个类中,我想使用
memcpy
方法:

template<typename T>class bar {
protected:
    T data;
public:
    bar() {}
    virtual ~bar() {}

    void read(unsigned char* readBuff, const std::size_t &readSize) {
        // Some stuff
        std::memcpy(readBuff, &(this->data), readSize);
        // Some stuff
    }
};
我得到了
4
,所以foo似乎正好是int的大小,所以我自然会认为直接读/写
x
,即使不指定
x.data
也会写数据。这是真的吗

我需要与C++11兼容。

对于具有虚函数的类,编译器通常会在类的开头插入一些元数据。不能假定实例的地址也是其第一个成员的地址

您可以使用
if constexpr
来区分这两种情况:

    if constexpr ( std::is_same_v<std::decay_t<T>, foo> ) {
        std::memcpy(readBuff, &(this->data.data), readSize);
    } else {
        std::memcpy(readBuff, &(this->data), readSize);
    }
如果constexpr(std::is_same_v){
std::memcpy(readBuff,&(this->data.data),readSize);
}否则{
std::memcpy(readBuff,&(this->data),readSize;
}

对于具有虚函数的类,编译器通常会在类的开头插入一些元数据。不能假定实例的地址也是其第一个成员的地址

您可以使用
if constexpr
来区分这两种情况:

    if constexpr ( std::is_same_v<std::decay_t<T>, foo> ) {
        std::memcpy(readBuff, &(this->data.data), readSize);
    } else {
        std::memcpy(readBuff, &(this->data), readSize);
    }
如果constexpr(std::is_same_v){
std::memcpy(readBuff,&(this->data.data),readSize);
}否则{
std::memcpy(readBuff,&(this->data),readSize;
}

具有虚拟成员的任意类型的布局由实现定义。不能保证在foo中偏移量为0的位置有
数据

您可以将
bar
完全专用于
foo

template<>class bar<foo> {
protected:
    foo data;
public:
    bar() {}
    virtual ~bar() {}

    void write(unsigned char* readBuff, const std::size_t &readSize) {
        // Some stuff
        std::memcpy(readBuff, &(this->data.data), readSize);
        // Some stuff
    }
};
没有

具有虚拟成员的任意类型的布局由实现定义。不能保证在foo中偏移量为0的位置有
数据

您可以将
bar
完全专用于
foo

template<>class bar<foo> {
protected:
    foo data;
public:
    bar() {}
    virtual ~bar() {}

    void write(unsigned char* readBuff, const std::size_t &readSize) {
        // Some stuff
        std::memcpy(readBuff, &(this->data.data), readSize);
        // Some stuff
    }
};

经过几次尝试,我找到了另一种实现它的方法,而不必像@Caleth的解决方案那样在read()中实例化一个新的
helper
对象(虽然这很好),因此哪个应该具有更好的性能:

class foo {
public:
    int data;

    foo(int dataIn) : data(dataIn) {}
    virtual ~foo() {}

    // Some other class methods
protected:
    // Some internal helper class methods
};

template<bool ISFOO> struct IsFoo_ {
    enum {
        IS_FOO_ = ISFOO
    };
};

template<typename T>class bar {
protected:
    T data;
public:
    bar() {}
    virtual ~bar() {}

    struct CRV {
        enum {
            USES_FOO = std::is_same<T, foo>::value
        };
    };

    void* getCopyable() {
        return getCopyable_<CRV::USES_FOO>();
    }

    void read(unsigned char* readBuff, const std::size_t &readSize) {
        // Some stuff
        std::memcpy(readBuff, this->getCopyable(), readSize);
        // Some stuff
    }

private:
    // Caller method
    template<bool ISFOO> inline void* getCopyable_() {
        return getCopyable_(IsBitVector_<ISFOO>());
    }
    // Generic method
    template<bool ISFOO> inline void* getCopyable_(IsFoo_<ISFOO>) {
        return nullptr;
    }
    // Specializations
    inline void* getCopyable_(IsFoo_<true>) {
        return reinterpret_cast<void*>(&(this->data.data));
    }
    inline void* getCopyable_(IsFoo_<false>) {
        return reinterpret_cast<void*>(&(this->data));
    }
};
class-foo{
公众:
int数据;
foo(int-dataIn):数据(dataIn){}
虚拟~foo(){}
//其他一些类方法
受保护的:
//一些内部助手类方法
};
模板结构IsFoo\u{
枚举{
IS_FOO=ISFOO
};
};
模板类栏{
受保护的:
T数据;
公众:
bar(){}
虚拟~bar(){}
结构CRV{
枚举{
USES\u FOO=std::is\u same::value
};
};
void*getCopyable(){
返回getCopyable_u2;();
}
无效读取(无符号字符*readBuff,常量std::size\u t和readSize){
//一些东西
std::memcpy(readBuff,this->getCopyable(),readSize);
//一些东西
}
私人:
//调用方方法
模板内联void*GetCopyTable{
返回getCopyable_u3;(IsBitVector_3;());
}
//通用方法
模板内联void*GetCopyTable(IsFoo){
返回空ptr;
}
//专业
内联void*getCopyable_u3;(IsFoo_3;){
返回reinterpret_cast(&(this->data.data));
}
内联void*getCopyable_u3;(IsFoo_3;){
返回reinterpret_cast(&(此->数据));
}
};

经过几次尝试,我找到了另一种实现它的方法,而不必像@Caleth的解决方案那样在read()中实例化一个新的
助手
对象(虽然这很好),因此哪个应该有更好的性能:

class foo {
public:
    int data;

    foo(int dataIn) : data(dataIn) {}
    virtual ~foo() {}

    // Some other class methods
protected:
    // Some internal helper class methods
};

template<bool ISFOO> struct IsFoo_ {
    enum {
        IS_FOO_ = ISFOO
    };
};

template<typename T>class bar {
protected:
    T data;
public:
    bar() {}
    virtual ~bar() {}

    struct CRV {
        enum {
            USES_FOO = std::is_same<T, foo>::value
        };
    };

    void* getCopyable() {
        return getCopyable_<CRV::USES_FOO>();
    }

    void read(unsigned char* readBuff, const std::size_t &readSize) {
        // Some stuff
        std::memcpy(readBuff, this->getCopyable(), readSize);
        // Some stuff
    }

private:
    // Caller method
    template<bool ISFOO> inline void* getCopyable_() {
        return getCopyable_(IsBitVector_<ISFOO>());
    }
    // Generic method
    template<bool ISFOO> inline void* getCopyable_(IsFoo_<ISFOO>) {
        return nullptr;
    }
    // Specializations
    inline void* getCopyable_(IsFoo_<true>) {
        return reinterpret_cast<void*>(&(this->data.data));
    }
    inline void* getCopyable_(IsFoo_<false>) {
        return reinterpret_cast<void*>(&(this->data));
    }
};
class-foo{
公众:
int数据;
foo(int-dataIn):数据(dataIn){}
虚拟~foo(){}
//其他一些类方法
受保护的:
//一些内部助手类方法
};
模板结构IsFoo\u{
枚举{
IS_FOO=ISFOO
};
};
模板类栏{
受保护的:
T数据;
公众:
bar(){}
虚拟~bar(){}
结构CRV{
枚举{
USES\u FOO=std::is\u same::value
};
};
void*getCopyable(){
返回getCopyable_u2;();
}
无效读取(无符号字符*readBuff,常量std::size\u t和readSize){
//一些东西
std::memcpy(readBuff,this->getCopyable(),readSize);
//一些东西
}
私人:
//调用方方法
模板内联void*GetCopyTable{
返回getCopyable_u3;(IsBitVector_3;());
}
//通用方法
模板内联void*GetCopyTable(IsFoo){
返回空ptr;
}
//专业
内联void*getCopyable_u3;(IsFoo_3;){
返回reinterpret_cast(&(this->data.data));
}
内联void*getCopyable_u3;(IsFoo_3;){
返回reinterpret_cast(&(此->数据));
}
};

您可以使用
offsetof
“如果您分配该类型的对象,并在结构的开头获得一个
字节*
,您可以使用
offsetof
找出每个成员的位置。如果您使用该指针偏移量,并将其转换回正确的类型,它将为您提供一个指向该成员的指针。”-.@user202729
offsetof
声明:“类型应该是一个标准布局类(包括联合)。”和“标准布局类是一个类[…]:(1)没有虚拟函数和虚拟基类。”@user202729正如WorldSEnder所说,文档说明在我的情况下这是未定义的行为。您可以使用
offsetof
。“如果分配该类型的对象,并在结构的开头获得一个
字节*
,则可以使用
offsetof
查找每个成员的位置。如果您使用该指针偏移量,并将其转换回正确的类型,它将为您提供一个指向成员的指针。“-@user202729
offsetof
声明:“类型应为标准布局类(包括联合)。”和“标准布局类为[…]类:(1)没有虚拟函数和虚拟基类。“@user202729正如WorldSEnder所说,文档中说在我的情况下这是未定义的行为。我忘了告诉我需要符合c++11。如果constexpr不工作!我忘了告诉你我需要什么