簡體   English   中英

如何在模板類函數中分配struct值?

[英]How to assign struct values in a template class function?

我有一堆結構需要添加到我的矢量並給它們一些默認值。

  1. 結構是外部的,我無法改變它們。
  2. 在分配這些值時,為了方便起見,我需要查看struct成員名稱。
  3. 為方便起見,我需要在同一個地方直觀地顯示所有默認值。
  4. 編譯器當前優化了myClass :: addStruct()中未使用的if分支 - 這正是我想要的。

問:可以用更好/更簡單的方式完成嗎?

編輯我沒有C ++ 17

//外部結構

typedef struct A {
    int member1;
    float member2;
    char *member3;
    // ...
} A;

typedef struct B {
    double member5;
    float member3;
    int *member4;
    // ...
} B;

typedef struct C {
    char* member5;
    char* member2;
    float *member3;
    // ...
} C;

...

template <class T>
void myClass::addStruct(std::vector<T> &vp)
{
    void *sp = nullptr;
    if(std::is_same<T, A>::value) {
        A s{};
        s.member1 = 2;
        s.member3 = "whatever";
        sp = &s;
    }
    else if(std::is_same<T, B>::value) {
        B s{};
        s.member4 = nullptr;
        s.member3 = 3.1f;
        sp = &s;
    }
    else if(std::is_same<T, C>::value) {
        C s{};
        s.member2 = "whenever";
        sp = &s;
    }
/*  else if() {
    }
    else if() {
    } ...
*/

    if(sp == nullptr) {
        // print error
        return;
    }

    vp.push_back(*(reinterpret_cast<T*>(sp)));
}

// usage

addStruct<A>(...);
addStruct<A>(...);
addStruct<B>(...);
addStruct<C>(...);
  1. 像這樣的代碼甚至不應該編譯,除非你使用constexpr(又名“靜態if”)。 它只是“有效”,因為你破壞了類型系統(整個void *和reinterpret_cast舞蹈)。 類型別名規則適用。
  2. 您正在獲取已超出范圍的對象的地址。 那是未定義的行為 ,現在工作時可能會在更改代碼或編譯器或只是編譯器版本時隨時中斷。
  3. 如果你真的想要使用該代碼,為什么不為不同的類型創建非模板重載? 方式更容易。
#include <vector>

typedef struct A {
    int member1;
    float member2;
    const char *member3;
    // ...
} A;

typedef struct B {
    double member5;
    float member3;
    int *member4;
    // ...
} B;

typedef struct C {
    char* member5;
    char* member2;
    float *member3;
    // ...
} C;

template <class T>
void addStruct(std::vector<T> &vp)
{
    // print error
}

template <>
void addStruct<A>(std::vector<A> &vp)
{
    A s{};
    s.member1 = 2;
    s.member3 = "whatever";
    vp.push_back(s);
}

template <>
void addStruct<B>(std::vector<B> &vp)
{
    B s{};
    s.member4 = nullptr;
    s.member3 = 3.1f;
    vp.push_back(s);
}

// ...

Trass3r之后的UPD:

#include <vector>

typedef struct A {
    int member1;
    float member2;
    const char *member3;
    // ...
} A;

typedef struct B {
    double member5;
    float member3;
    int *member4;
    // ...
} B;

typedef struct C {
    char* member5;
    char* member2;
    float *member3;
    // ...
} C;

void addStruct(std::vector<A> &vp)
{
    A s{};
    s.member1 = 2;
    s.member3 = "whatever";
    vp.push_back(s);
}

void addStruct(std::vector<B> &vp)
{
    B s{};
    s.member4 = nullptr;
    s.member3 = 3.1f;
    vp.push_back(s);
}

// ...

創建工廠方法:

template <typename T> struct Tag {};

A MakeDefault(Tag<A>) {
    A a{};
    a.member1 = 2;
    a.member3 = "whatever";
    return a;
}

B MakeDefault(Tag<B>) {
    B b{};
    b.member4 = nullptr;
    b.member3 = 3.1f;
    return b;
}

C MakeDefault(Tag<C>) {
    C c{};
    c.member2 = "whenever";
    return c;
}

// ...

template <class T>
void myClass::addStruct(std::vector<T> &vp)
{
    vp.push_back(MakeDefault(tag<T>{}));
}

我使用標簽調度而不是模板專業化,這在這里看起來更簡單。

問:可以用更好/更簡單的方式完成嗎?

是的:通過使用功能多態(具有相同名稱和不同參數的函數),可以在沒有模板的情況下完成。

typedef struct A {
    int member1;
    float member2;
    char *member3;
    // ...
} A;

typedef struct B {
    double member5;
    float member3;
    int *member4;
    // ...
} B;

...

void myClass::addStruct(std::vector<A>& v)
{
    v.push_back({0});
    v.back().member1 = 2;
    v.back().member3 = "whatever";
}

void myClass::addStruct(std::vector<B>& v)
{
    v.push_back({0});
    // v.back().member4 = nullptr; // this is unnecessary now
    v.back().member3 = 3.1f;
}

...

// usage

std::vector<A> va;
std::vector<B> vb;

myClass c;
c.addStruct(va);
c.addStruct(vb);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM