2つのヘッダに同名の構造体とクラスが…

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
lopple
記事: 3
登録日時: 3年前

2つのヘッダに同名の構造体とクラスが…

#1

投稿記事 by lopple » 3年前

初めまして。
C++を触り始めて1ヶ月ほどの者で、本掲示板に初めての投稿です。
よろしくお願いいたします。

題目の件についてですが、現在KinectとOculus Riftを用いたシステムを作っています。
ここでKinect側のヘッダファイル<Nuisensor.h>とRift側のヘッダファイル<OVR_Math.h>の中に、同名"Vector4"の構造体とクラスが存在し、ビルド時に”あいまいなシンボルです”と弾かれてしまいます。
どちらも公式SDKのヘッダファイルなので、書き換えずに衝突を防ぐにはどのように記述すればよろしいでしょうか。
何卒、ご教示ください。

以下にそれぞれのヘッダファイルの衝突部分を記載いたします。

コード:

//Nuisensor.h
#ifndef _Vector4_
#define _Vector4_
typedef struct _Vector4
    {
    FLOAT x;
    FLOAT y;
    FLOAT z;
    FLOAT w;
    } 	Vector4;

#endif _Vector4_

コード:

//OVR_Math.h
// ***** Vector4<> - 4D vector of {x, y, z, w}

//
// Vector4f (Vector4d) represents a 3-dimensional vector or point in space,
// consisting of coordinates x, y, z and w.

template<class T>
class Vector4
{
public:
    typedef T ElementType;
    static const size_t ElementCount = 4;

    T x, y, z, w;

    // FIXME: default initialization of a vector class can be very expensive in a full-blown
    // application.  A few hundred thousand vector constructions is not unlikely and can add
    // up to milliseconds of time on processors like the PS3 PPU.
    Vector4() : x(0), y(0), z(0), w(0) { }
    Vector4(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { }
    explicit Vector4(T s) : x(s), y(s), z(s), w(s) { }
    explicit Vector4(const Vector3<T>& v, const T w_=T(1)) : x(v.x), y(v.y), z(v.z), w(w_) { }
    explicit Vector4(const Vector4<typename Math<T>::OtherFloatType> &src)
        : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { }

    static Vector4 Zero() { return Vector4(0, 0, 0, 0); }

    // C-interop support.
    typedef  typename CompatibleTypes< Vector4<T> >::Type CompatibleType;

    Vector4(const CompatibleType& s) : x(s.x), y(s.y), z(s.z), w(s.w) {  }

    operator const CompatibleType& () const
    {
        OVR_MATH_STATIC_ASSERT(sizeof(Vector4<T>) == sizeof(CompatibleType), "sizeof(Vector4<T>) failure");
        return reinterpret_cast<const CompatibleType&>(*this);
    }

    Vector4& operator= (const Vector3<T>& other)  { x=other.x; y=other.y; z=other.z; w=1; return *this; }
    bool     operator== (const Vector4& b) const  { return x == b.x && y == b.y && z == b.z && w == b.w; }
    bool     operator!= (const Vector4& b) const  { return x != b.x || y != b.y || z != b.z || w != b.w; }
             
    Vector4  operator+  (const Vector4& b) const  { return Vector4(x + b.x, y + b.y, z + b.z, w + b.w); }
    Vector4& operator+= (const Vector4& b)        { x += b.x; y += b.y; z += b.z; w += b.w; return *this; }
    Vector4  operator-  (const Vector4& b) const  { return Vector4(x - b.x, y - b.y, z - b.z, w - b.w); }
    Vector4& operator-= (const Vector4& b)        { x -= b.x; y -= b.y; z -= b.z; w -= b.w; return *this; }
    Vector4  operator- () const                   { return Vector4(-x, -y, -z, -w); }

    // Scalar multiplication/division scales vector.
    Vector4  operator*  (T s) const               { return Vector4(x*s, y*s, z*s, w*s); }
    Vector4& operator*= (T s)                     { x *= s; y *= s; z *= s; w *= s;return *this; }

    Vector4  operator/  (T s) const               { T rcp = T(1)/s;
                                                    return Vector4(x*rcp, y*rcp, z*rcp, w*rcp); }
    Vector4& operator/= (T s)                     { T rcp = T(1)/s;
                                                    x *= rcp; y *= rcp; z *= rcp; w *= rcp;
                                                    return *this; }

    static Vector4  Min(const Vector4& a, const Vector4& b)
    {
        return Vector4((a.x < b.x) ? a.x : b.x,
                       (a.y < b.y) ? a.y : b.y,
                       (a.z < b.z) ? a.z : b.z,
                       (a.w < b.w) ? a.w : b.w);
    }
    static Vector4  Max(const Vector4& a, const Vector4& b)
    { 
        return Vector4((a.x > b.x) ? a.x : b.x,
                       (a.y > b.y) ? a.y : b.y,
                       (a.z > b.z) ? a.z : b.z,
                       (a.w > b.w) ? a.w : b.w);
    }        

    Vector4 Clamped(T maxMag) const
    {
        T magSquared = LengthSq();
        if (magSquared <= Sqr(maxMag))
            return *this;
        else
            return *this * (maxMag / sqrt(magSquared));
    }

    // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
    bool IsEqual(const Vector4& b, T tolerance = Math<T>::Tolerance()) const
    {
        return (fabs(b.x-x) <= tolerance) && 
               (fabs(b.y-y) <= tolerance) && 
               (fabs(b.z-z) <= tolerance) &&
               (fabs(b.w-w) <= tolerance);
    }
    bool Compare(const Vector4& b, T tolerance = Math<T>::Tolerance()) const
    {
        return IsEqual(b, tolerance);
    }
    
    T& operator[] (int idx)
    {
        OVR_MATH_ASSERT(0 <= idx && idx < 4);
        return *(&x + idx);
    }

    const T& operator[] (int idx) const
    {
        OVR_MATH_ASSERT(0 <= idx && idx < 4);
        return *(&x + idx);
    }

    // Entry wise product of two vectors
    Vector4    EntrywiseMultiply(const Vector4& b) const    { return Vector4(x * b.x, 
                                                                         y * b.y, 
                                                                         z * b.z,
                                                                         w * b.w);}

    // Multiply and divide operators do entry-wise math
    Vector4  operator*  (const Vector4& b) const        { return Vector4(x * b.x, 
                                                                         y * b.y, 
                                                                         z * b.z,
                                                                         w * b.w); }

    Vector4  operator/  (const Vector4& b) const        { return Vector4(x / b.x, 
                                                                         y / b.y, 
                                                                         z / b.z,
                                                                         w / b.w); }


    // Dot product
    T       Dot(const Vector4& b) const          { return x*b.x + y*b.y + z*b.z + w*b.w; }

    // Return Length of the vector squared.
    T       LengthSq() const                     { return (x * x + y * y + z * z + w * w); }

    // Return vector length.
    T       Length() const                       { return sqrt(LengthSq()); }
    
    bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance(); }

    // Normalize, convention vector length to 1.    
    void    Normalize()                          
    {
        T s = Length();
        if (s != T(0))
            s = T(1) / s;
        *this *= s;
    }

    // Returns normalized (unit) version of the vector without modifying itself.
    Vector4 Normalized() const                   
    { 
        T s = Length();
        if (s != T(0))
            s = T(1) / s;
        return *this * s;
    }

    // Linearly interpolates from this vector to another.
    // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
    Vector4 Lerp(const Vector4& b, T f) const    { return *this*(T(1) - f) + b*f; }
};

typedef Vector4<float>  Vector4f;
typedef Vector4<double> Vector4d;
typedef Vector4<int>    Vector4i;

inemaru
記事: 108
登録日時: 3年前

Re: 2つのヘッダに同名の構造体とクラスが…

#2

投稿記事 by inemaru » 3年前

自分は、「Kinect」と「Oculus Rift」のどちらのSDKも使用したことが無いので

「別々のファイルにある定義が衝突するが、定義を書き換えず呼び出し元で解決したい」
と解釈して回答します、ご了承ください。

定義そのものを、名前空間に閉じ込める方法で
とりあえずの解決は、できると思います。

以下、参考コードです

コード:

namespace Kinect
{
#include "Nuisensor.h"
}

namespace Oculus
{
#include "OVR_Math.h"
}

int main()
{
	// 使用するときは、スコープを使って区別する
	Kinect::Vector4			kinectVec;
	Oculus::Vector4<float>	oculusVec;

	return 0;
}
おそらく正攻法ではないと思うので、
この方法を使ったことで別の問題が起こるかもしれません。
オフトピック
本来、C++向けのライブラリやSDKは名前衝突を回避するために名前空間に定義されているものなので、
自分は、名前衝突の問題に直面したことがありません。
もっと良い解決方法(正攻法)があるかもしれません。

閉鎖

“C言語何でも質問掲示板” へ戻る