Сегодня я столкнулся с довольно странной проблемой.У меня есть математическая библиотека, оптимизированная для SSE, поэтому почти вся функциональность объявлена как встроенная.Для упрощения я объясню проблему, используя только один класс, Vector3:
Vector3 объявлен в Vector3.h, примерно так:
#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
В vector3.inl я продолжаю определятьвсе функции
namespace Virtus {
Vector3::Vector3(void)
: 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;
}
...
Затем я включаю все мои математические объекты в файл с именем 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
, а math.h включается в мой предварительно скомпилированный заголовочный файл (предварительно скомпилированный.h aka stdafx.h)
Я использую Visual Studio 2008, которая должна автоматически исключать файлы .inl из процесса сборки.
Это ошибка компоновщика, которую я получаю:
Ошибка 1, ошибка LNK2005: «public: __thiscall Virtus :: Vector3 :: Vector3 (void)» (?? 0Vector3 @ Virtus @@ QAE @ XZ) уже определен в precompiled.obj main.obj Virtus
Я пытался исправить это практически всеми возможными способами, например, исключить все входящие файлы из сборки вручную;не включая math.h в предварительно скомпилированный файл, а только там, где он мне нужен (в этом случае я получаю аналогичную уже определенную ошибку компоновщика);переход от расширения inl к расширению cpp и так далее.Единственный способ, которым я смог это исправить, это использовать один раз #pragma вместо include guard.Поэтому сейчас я думаю, что это как-то связано с комбинацией предварительно скомпилированных заголовочных файлов и включенных средств защиты, но я не совсем уверен, как это исправить.
Помощь будет очень признательна!