I came about a rather weird problem today. I have a math library optimized for SSE, therefore almost all functionality is declared as inline. For simplification purposes I will only explain the problem using one class, Vector3:
Vector3 is declared in Vector3.h, something like this:
#ifndef VIRTUS_VECTOR3_H
#define VIRTUS_VECTOR3_H
#ifndef VEC3INLINE
#if(_DEBUG)
#define VEC3INLINE inline
#else
#define VEC3INLINE __forceinline
#endif
#endif
namespace Virtus {
struct Vector3
{
union
{
struct { f32 x,y,z; };
f32 v[3];
};
Vector3(void);
Vector3(const Vector3& rhs);
Vector3(f32 xx, f32 yy, f32 zz);
VEC3INLINE Vector3& operator=(const Vector3& rhs);
VEC3INLINE Vector3 operator+(f32 rhs) const;
VEC3INLINE Vector3 operator-(f32 rhs) const;
VEC3INLINE Vector3 operator*(f32 rhs) const;
VEC3INLINE Vector3 operator/(f32 rhs) const;
VEC3INLINE Vector3& operator+=(f32 rhs);
VEC3INLINE Vector3& operator-=(f32 rhs);
...
#include "vector3.inl"
#endif
In vector3.inl I proceed with defining all of the functions
namespace Virtus {
Vector3::Vector3(void开发者_StackOverflow)
: x(0.0f), y(0.0f), z(0.0f)
{
}
Vector3::Vector3(const Vector3& rhs)
: x(rhs.x), y(rhs.y), z(rhs.z)
{
}
Vector3::Vector3(f32 xx, f32 yy, f32 zz)
: x(xx), y(yy), z(zz)
{
}
VEC3INLINE Vector3& Vector3::operator=(const Vector3& rhs)
{
memcpy(v, rhs.v, sizeof(v));
return *this;
}
...
I then include all of my math objects in a file called math.h
#ifndef VIRTUS_MATH_H
#define VIRTUS_MATH_H
#include "vector2.h"
#include "vector3.h"
#include "vector4.h"
#include "matrix4.h"
#include "primesearch.h"
namespace Virtus
{
class MathException
{
public:
enum ErrorCode
{
PRIME_SEARCH_INVALID_ELEMENTS,
PRIME_SEARCH_UNSUFFNUM_PRIMES
};
MathException(ErrorCode code) : m_Error(code) {}
ErrorCode What(void) const { return m_Error; }
private:
ErrorCode m_Error;
};
} // namespace virtus
#endif // Include Guard
and math.h is included in my precompiled header file (precompiled.h aka stdafx.h)
I use Visual Studio 2008, which should automatically exclude .inl files from the build process.
This is the linker error I am getting:
Error 1 error LNK2005: "public: __thiscall Virtus::Vector3::Vector3(void)" (??0Vector3@Virtus@@QAE@XZ) already defined in precompiled.obj main.obj Virtus
I tried fixing this pretty much every way imaginable, like excluding all inl files from the build manually; not including math.h in the precompiled file but only where I need it ( in which case I get a similar already defined linker error); changing from the inl extension to cpp extension, and so on. The only way I was able to fix it was using #pragma once instead of include guards. So my best guess at this time is that it has something to do with the combination of precompiled header files and include guards, but I'm not really sure how to fix this.
Help would be much appreciated!
Each of the definitions inside vector3.inl needs to be explicitly defined with inline
.
精彩评论