我使用gcc 4.7.3 for ARM平台来编译我的代码。我有几个这样的课程:
// 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;
// ...
};
我使用这些类的源代码中的某处:
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));
}
};
获取下一条消息(在链接期间):
undefined reference to `D1::kType`
undefined reference to `D2::kType`
// more messages of this type
行。如果我像这样更改do_something函数:
template<typename T>
void doSomething(MyObject obj)
{
mm_.insert(std::multimap<int, MyObject>::value_type( (int) T::type, obj));
}
它编译好了。但为什么?关于它的标准找不到任何东西。有没有人对正在发生的事情有所了解?
感谢。
P.S。
此修复
// d1.cpp
const int D1::kType;
也有效,但这是预期的。
P.P.S。在使用引用或指向T :: type的情况下,答案是非常明显的,但我没有看到任何需要ref或ptr的东西。 AFAIK std :: multimap :: value_type按值(不是ref,也不是ptr)获取参数。
答案 0 :(得分:1)
// d1.cpp
const int D1::kType;
// d2.cpp
const int D2::kType;
就是答案,
//d1.h
public:
static const int type = kType1;
就像一个函数原型,它被编译到包含头的每个复杂对象(cpp文件)中,因此由于ODR规则它实际上不保留内存空间,否则链接器会发现很多每个编译单元中包含标题的变量实例。
因此,您需要一个编译单元(一个cpp文件),它定义将用于多次使用的标头中找到的类常量的实际内存空间。