今天我第一次编译了我的代码库,并使用 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([=]() {
异步看起来像这样:
void Async(const Functor<void> &f) {
// ....
}
奇怪的是,函子没有在析构函数中声明,不会产生警告。我觉得 gcc 正在生成这些导致冲突的 2 个版本。