ネストされたデータメンバポインタ - ことができませんか?

StackOverflow https://stackoverflow.com/questions/3439074

  •  27-09-2019
  •  | 
  •  

質問

foolowing削減のコードサンプルは、データメンバポインタには何の役に立つが、2つの後続の割り当てを行いません。最初assignementの作品は、もう一つは、コンパイラのエラーを示します。おそらく、そのネストされたメンバーに。

質問は次のようになります?それは、ネストされたメンバーへのメンバーポインタポイントをできるように実際には可能ではないか、私はどんな派手な構文をしないのですが。

struct Color {
    float Red;
    float Green;
    float Blue; };


struct Material {
    float Brightness;
    Color DiffuseColor; };


int main() {
    float Material::* ParamToAnimate;
    ParamToAnimate = &Material::Brightness;       // Ok
    ParamToAnimate = &Material::DiffuseColor.Red; // Error! *whimper*
    return 0; }

ATM私はバイトオフセットやキャストの多くを使用して周りに働いています。しかし、それは私がより良いものをメンバーポインタを使用したい、醜いです。

はい、私は確かに前に(ほぼすべての質問のように)arisedその質問を知っています。はい、私は事前に検索が、何の条件を満たす答えを見つけていない。

あなたの時間をありがとう。

役に立ちましたか?

解決

私の知る限りでは、これは不可能です。ポインタ・ツー・メンバーのみ、あなたのケースではないタイプ&qualified_idの発現によって形成することができる。

ヴィーテファルコンのソリューションは、おそらく最も適切である。

他のヒント

私はあなたのデータメンバーRedへのポインタを取得しようとしていると仮定します。これは、構造体Colorで定義されているので、ポインタの種類がColor::*あります。したがって、あなたのコードは次のようになります。

int main() {
    float Color::* ParamToAnimate;
    ParamToAnimate = &Color::Red; 
    return 0; }

これを使用するには、例えばColorのインスタンスにバインドする必要があります:

void f(Color* p, float Color::* pParam)
{
    p->*pParam = 10.0;
}
int main() {
    float Color::* ParamToAnimate;
    ParamToAnimate = &Color::Red; 

    Material m;
    f(&m.DiffuseColor, ParamToAnimate);
    return 0;
}

編集:それはアニメーション機能テンプレートにすることが可能ではないですか?たとえばます:

template<class T>
void f(T* p, float T::* pParam)
{
    p->*pParam = 10.0;
}
int main() {

    Material m;

    f(&m.DiffuseColor, &Color::Red);
    f(&m, &Material::Brightness);
    return 0;
}
代わり部材ポインタの

、あなたがfloat*のインスタンスが与えられたときMaterialを返すファンクタを使用することができます。以下のようなものにParamToAnimateの種類を変更します:

std::function<float*(Material&)>

はプラス側では、それはポータブルだ - 。しかし、下側に、それは定型コードを大量に必要とし、重要な実行時のオーバーヘッドを持っている。

これは重要なパフォーマンスである場合は、

、私はオフセット法でスティックに誘惑されると思います。

基本的にはあなたがアニメーション化できることフロート変数へのポインタを取得しようとしています。なぜfloat*を使用していません。あなたはそのBrightnessがある抱えている問題は、材質のメンバーである、しかし、Redは、コンパイラに、ColorなくMaterialのメンバーです。 float*を使用すると、あなたの問題を解決する必要があります。

それは不可能です。しかし、非常に近い、あなたが達成したいものに回避策があります。それは、「レイアウトの互換性」の匿名の構造体と一緒に労働組合にネストされたメンバーを置く必要とします。欠点は、ビット肥大化インターフェースと同期して構造体を兄弟の定義を維持する必要があることである。

struct Color {
    float Red;
    float Green;
    float Blue; };

struct Material {
    float Brightness;
    union {
        struct { // "Layout-compatible" with 'Color' (see citation below)
            float DiffuseColorRed;
            float DiffuseColorGreen;
            float DiffuseColorBlue; };
        Color DiffuseColor; }; };

int main() {
    Material M;

    float Material::* ParamToAnimate;
    ParamToAnimate = &Material::DiffuseColorRed;
    std::cin >> M.*ParamToAnimate;
    std::cout << M.DiffuseColor.Red << std::endl;
    return 0; }

ISO IEC 14882-2003(C ++ 03):

  

§3.9

     

11

     二種類のT1及びT2は同じタイプである場合、

は、T1とT2は   レイアウト互換タイプ。 [注:レイアウトと互換性の列挙であります   7.2で説明しました。レイアウト互換POD-構造体とPOD-組合があります   9.2で説明しました。

     

§9.2

     

16

     

POD-組合は、共通を共有する2つ以上のPOD-構造体が含まれている場合   初期シーケンス、およびPOD-組合のオブジェクトが現在1が含まれている場合   これらのPOD-構造体のために、それは共通の初期を検査することが許可されます   それらのいずれかの部分。二POD-構造体は、共通の初期シーケンスを共有します   対応する部材は、レイアウト互換型(及び、用がある場合   一つ又は複数の初期のシーケンスに対するビットフィールド、同じ幅)   メンバーます。

複数のネストがあまりにも可能です。

struct Color {
    float Red;
    float Green;
    float Blue; };

struct Material {
    float Brightness;
    Color DiffuseColor; };

struct Wall {
    union {
        struct {
            float SurfaceBrightness;
            struct {
                float SurfaceDiffuseColorRed;
                float SurfaceDiffuseColorGreen;
                float SurfaceDiffuseColorBlue; }; };
        Material Surface; }; };

int main() {
    Wall W;

    float Wall::* ParamToAnimate;
    ParamToAnimate = &Wall::SurfaceDiffuseColorRed;
    std::cin >> W.*ParamToAnimate;
    std::cout << W.Surface.DiffuseColor.Red << std::endl;
    return 0; }
  

§9.2

     

14

     彼らが持っている場合は、

二つのPOD-構造体(条項9)タイプ、レイアウト、互換性があります   非静的データメンバの同じ数、および対応する非静的   データメンバー(順番に)は、レイアウト互換型(3.9)を有する。

あなたは、単にあなたがすべてのネストされた構造を有していないようにリファクタリングができます。したがって、既存のコードの必要性はあまり変化しないことをそのコンポーネント部分にアンパックよりも色をセッターを追加し、そこから行くます。

また、ネストされたタイプに食い込むオプションの第2のポインタを取ることができます。あなたは二番目のパラメータを必要とするかどうかを確認するために、単一のテストは、あなたの現在の方法に比べて十分に良いことを証明することができ、追加のフィールドは、後に上げる必要があり、より容易に拡張されるだろう。

ステップはさらに、あなたは仮想MaterialPointer方法と基本Dereferenceクラスを持っていることを取ります。ケースクラスは、彼らがそれらを見つけるために必要な追加的な情報をとネストされたメンバーを扱う派生クラスで、簡単なメンバーを処理することができます。工場は、適切なタイプのMaterialMember*オブジェクトを生成することができます。もちろん、今しているヒープの割り当てにこだわって、これはあまりにも遠く実用的である可能性が高い少しあるのでます。

いくつかの点であなたは実際のデータへのポインタを必要とするので、このかもしれないまたはかもしれないあなたのために仕事ます:

float Material::* ParamToAnimate;
ParamToAnimate = &Material::Brightness;       // Ok
float Color::* Param2;
Param2 = &Color::Red; 

Material mat;
mat.Brightness = 1.23f;
mat.DiffuseColor.Blue = 1.0f;
mat.DiffuseColor.Green = 2.0f;
mat.DiffuseColor.Red = 3.0f;

float f = mat.DiffuseColor.*Param2;

どのように代わりの組成物の継承について?

struct Color {
    float Red;
    float Green;
    float Blue; };

struct DiffuseColor : public Color {
    };

struct Material : public DiffuseColor {
    float Brightness; };


int main() {
    float Material::* ParamToAnimate;
    ParamToAnimate = &Material::Brightness;       // Ok
    ParamToAnimate = &Material::DiffuseColor::Red; // Ok! *whew*
    return 0; }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top