構造体の初期化

[戻る]
亀山 2008/10/22(水) 16:24:19
struct Test {
    int a;
    CString b;
};

Test test[] = {
    { 1, _T("1"), },
    { 2, _T("2"), },
    { 3, _T("3"), },
    { 4, _T("4"), },
};

という構造体初期化の試作コードを入れてみたところ、
VC2005では問題無くコンパイルが通りますが、
VC6では
'const int' から 'struct Test' に変換することはできません。
'char [2]' から 'struct Test' に変換することはできません。
といったエラーがズラズラ出てきます。

これはなにかVC6時代の制限でもあるのでしょうか?
それとも、このような初期化自体が正しい方法ではないのでしょうか?

bun 2008/10/22(水) 17:54:15
struct Test {
    int a;
    LPCTSTR b;
};
にすれば通ります。

VC6は構造体初期化時に型変換できないのかな?

Jason 2008/10/22(水) 19:22:59
VC6など低レベルコンパイルの問題でしょう?

実はCStringもポイントですけど。。。

亀山 2008/10/24(金) 09:34:15
[[解決]]
情報ありがとうございます。
この構造体の初期化自体は間違った方法ではなく、
やはりVC6のコンパイラに制限があるのですね。

CStringをLPCTSTRに置き換えると確かに通りました。
これだとインスタンス生成後に文字列を変更する作業がかなり面倒そうですが、
現在のところは文字列自体は変更することは無く、
仕様上VC6でもコンパイルが通るようにしておかなければいけないため、
この方法で対応しておこうと思います。

wclrp ( 'o') 2008/10/25(土) 01:51:19
以前経験したことあるな。

言語的にどういう規則なのかは知らない。

うろ覚えなので以下で成功するのか不明。VC6が使えないので確認しない。
生成されるコードがVC2005と同等に最適化されたものになるのかどうかは知らない。

解決案 1

struct Test {
    int a;
    CString b;
#if VC6
    Test(int foo, LPCTSTR bar) : a(foo), b(bar) {  }
#endif
};

解決案 2

#if VC6
    xCString(x) CString(x)
#else
    xCString(x) x
#endif

Test test[] = {
    { 1, xCString(_T("1")) },
    { 2, xCString(_T("2")) },
    { 3, xCString(_T("3")) },
    { 4, xCString(_T("4")) },
};

亀山 2008/10/27(月) 10:07:47
情報ありがとうございます。

解決案1のように

struct Test {
    int a;
    CString b;
    Test(int foo, LPCTSTR bar) : a(foo), b(bar) {  }
};

Test test[] = {
    { Test(1, _T("1")), },
    { Test(2, _T("2")), },
    { Test(3, _T("3")), },
    { Test(4, _T("4")), },
};

と書いてみたところ、VC6では通りましたが、今度はVC2005のほうで
「ユーザー定義のコンストラクタを含む型はアグリゲートではありません」
というエラーが出るようになりました。
初期化方法自体もコンパイラの種類で分けなくてはいけないのでしょうか。

解決案2のほうは、VC6上で

struct Test {
    int a;
    CString b;
};

Test test[] = {
    { int(1), CString(_T("1")), },
    { int(2), CString(_T("2")), },
    { int(3), CString(_T("3")), },
    { int(4), CString(_T("4")), },
};

と明示的に型を明示してもエラーは消えませんでした。

ISLe 2008/10/29(水) 16:02:33
VC6はC++の規格が曖昧だった頃に作られた古い処理系なのでその辺りの問題は2005以降
はコンパイラ毎に区別する必要は無いと思います。

まえだ 2008/11/05(水) 10:53:21
> インスタンス生成後に文字列を変更する作業がかなり面倒そう

こんなのどうですか?

struct Test {
    int a;
    CString b;
    
    Test(int aa, LPCTSTR bb)
    {
        a = aa;
        b = bb;
    }
};

Test test[] = {
    Test(1, _T("1")),
    Test(2, _T("2")),
    Test(3, _T("3")),
    Test(4, _T("4")),
};

まえだ 2008/11/05(水) 11:14:12
ごめんなさい。既出でしたね。

亀山 2008/11/05(水) 12:24:09
[[解決]]
ちょっとトラブっていて返答が遅れてしまいました。
ISLeさん、まえださん、情報ありがとうございます。

Test test[] = {
    Test(1, _T("1")),
    Test(2, _T("2")),
    Test(3, _T("3")),
    Test(4, _T("4")),
};

のコンストラクタを使う方法だとVC6でもVC2005でも通りました。
2008/10/27(月)10:07:47の「アグリゲートではありません」という
エラーが出たときと同じではと思って前の書き込みを再度読んでみたところ、
コンストラクタを{}で囲ってしまっていました。
VC6で通ってしまっていたので気づきませんでした(恥)。

ありがとうございます。

古いスレッドには追加発言できません。