anggota static const int dan referensi tidak terdefinisi

Saya menggunakan gcc 4.7.3 untuk platform ARM untuk mengkompilasi kode saya. Saya memiliki beberapa kelas seperti ini:

// types.h
enum Types
{
    kType1,
    kType2
    // ...
};

// d1.h
class D1 : public Base
{
public:
    static const int type = kType1;
    // ...
};

// d2.h
class D2 : public Base
{
public:
    static const int type = kType2;
    // ...
};

Di suatu tempat di sumber saya menggunakan kelas-kelas itu:

MyObject obj;
doSomething<D1>(obj);
doSomething<D2>(obj);

// other.cpp
class Foo
{
    template<typename T>
    void doSomething(MyObject obj)
    {
        mm_.insert(std::multimap<int, MyObject>::value_type(T::type, obj));
    }
};

Dan dapatkan pesan berikutnya (saat menghubungkan):

undefined reference to `D1::kType`
undefined reference to `D2::kType`
// more messages of this type

OKE. Jika saya mengubah fungsi do_something seperti ini:

template<typename T>
void doSomething(MyObject obj)
{
    mm_.insert(std::multimap<int, MyObject>::value_type( (int) T::type, obj));
}

itu dikompilasi dengan OK. Tapi kenapa? Tidak dapat menemukan apa pun dalam standar tentang hal itu. Adakah yang punya ide tentang apa yang terjadi?

Terima kasih.

P.S.

Perbaikan ini

 // d1.cpp
 const int D1::kType;

juga berfungsi, tetapi ini diharapkan.

PPS jawabannya akan cukup jelas jika menggunakan referensi atau penunjuk ke T::type, tapi saya tidak melihat apa pun yang memerlukan ref atau ptr. AFAIK std::multimap::value_type ambil argumen berdasarkan nilai (bukan ref, atau ptr).


person maverik    schedule 03.07.2013    source sumber
comment
Bukankah Anda seharusnya merujuk T::type dan bukan T::kType?   -  person Timo Geusch    schedule 03.07.2013
comment
@TimoGeusch, ya, terima kasih. Tetap   -  person maverik    schedule 03.07.2013
comment
Apakah Anda yakin apa yang disampaikan Timo tidak menyelesaikan masalah? Karena sepertinya tautannya mencari D1::kType, itulah yang diminta template Anda.   -  person Mats Petersson    schedule 03.07.2013
comment
@MatsPetersson, Itu hanya salah ketik dalam pertanyaan. Kode sebenarnya menggunakan anggota yang tepat.   -  person maverik    schedule 03.07.2013
comment
Anda mungkin harus memposting kode sebenarnya karena kode di atas terlihat tidak berbahaya dan OK, setidaknya bagi saya.   -  person Timo Geusch    schedule 03.07.2013
comment
pertanyaan terkait.   -  person maverik    schedule 03.07.2013
comment
@maverik harap berikan SSCCE. Saya mencoba memperluas potongan-potongan yang Anda tinggalkan kepada kami, namun gcc mengkompilasinya dengan cukup baik: ideone.com/CTu1UD - jadi gcc-4.7.2 tidak dapat menemukan kesalahan, begitu pula kami, setidaknya dengan melihat kode dan menebak apa yang hilang.   -  person Arne Mertz    schedule 03.07.2013
comment
@TimoGeusch, sayangnya ini cukup besar dan sulit untuk memotongnya menjadi contoh minimal yang dapat dikompilasi. Tapi saya akan mencoba   -  person maverik    schedule 03.07.2013
comment
Dengan menguranginya, kemungkinan besar Anda akan menemukan masalah sebenarnya - kemungkinan besar itu adalah kesalahan ketik yang mirip dengan masalah yang baru saja Anda alami.   -  person Mats Petersson    schedule 03.07.2013
comment
std::multimap<T,U>::value_type adalah std::pair<const T,U> yang konstruktornya mengambil const& T, const& U. FWIW.   -  person rici    schedule 03.07.2013
comment
Masalah sebenarnya adalah banyak potongan kode ini ada di file header. Jadi cukup sulit untuk membuat contoh sederhana untuk menunjukkan kasusnya. Dan jika saya memasukkan hal-hal itu ke dalam cpp maka ini tidak akan relevan.   -  person maverik    schedule 03.07.2013
comment
@rici: sekarang masuk akal (dan saya bisa mengerti mengapa cast memecahkan masalah).   -  person maverik    schedule 03.07.2013


Jawaban (1)


// d1.cpp
const int D1::kType;

// d2.cpp
const int D2::kType;

adalah jawabannya,

//d1.h
public:
    static const int type = kType1;

Seperti prototipe fungsi, ia dikompilasi ke dalam setiap objek komplikasi (file cpp) yang menyertakan header, sehingga karena aturan ODR ia tidak benar-benar mencadangkan ruang memori, atau tautannya akan menemukan banyak contoh dari variabel di setiap unit kompilasi yang menyertakan header.

Oleh karena itu, Anda memerlukan satu unit kompilasi (file cpp) yang menentukan ruang memori sebenarnya yang akan digunakan untuk konstanta kelas yang ditemukan di header yang digunakan beberapa kali.

person Strings    schedule 20.09.2013