今天我第一次编译了我的代码库,并使用gcc 5.1启用了链接时优化,我收到了奇怪的ODR警告:
Functor.h:67:8: warning: type 'struct Func' violates one definition rule [-Wodr]
class Func : public FuncBase
Functor.h:67:8: note: a different type is defined in another translation unit
class Func : public FuncBase
代码如下:
template<typename R, typename... Args>
class Functor
{
class FuncBase : NonCopyable
{
public:
FuncBase() {
}
virtual ~FuncBase() {
}
virtual R apply(Args...) = 0;
};
template<typename T>
class Func : public FuncBase
{
public:
Func(const T &t) : f(t) {
}
virtual ~Func() {
}
virtual R apply(Args... args) override {
return f(args...);
}
private:
T f;
};
/* ... */
std::shared_ptr<FuncBase> func;
public:
template<typename T>
Functor(const T &t) : func(new Func<T>(t)) {
}
};
如您所见,Func与自身发生冲突。
gcc如何在模板类中找到ODR问题? 我完全不了解ODR,但我觉得应该有'多次声明'错误。
注意:成员f似乎是问题的根源:
Functor.h:81:6: note: a field of same name but different type is defined in another translation unit
T f;
注2: 问题似乎只有在我在析构函数中构造一个Functor时才出现:
UniformBuffer.h:40:26: note: type name 'DynamicBuffer::Data::~Data(int)::{lambda()#1}' should match type name 'DynamicBuffer::Data::~Data()::{lambda()#1}'
Async([=]() {
UniformBuffer.h:40:26: note: the incompatible type is defined here
Async([=]() {
Async看起来像这样:
void Async(const Functor<void> &f) {
// ....
}
很奇怪,仿函数没有在析构函数中声明,也没有生成警告。我觉得gcc正在产生2个版本,导致冲突。