2015-11-18 81 views
0

我已成功地編譯和運行C++代碼即使它不應該。成員仍然是公開可見

下面的代碼片段不被編譯:

template<typename T, size_t SIZE> 
struct Vector { 
    Vector(std::initializer_list<T> data) { 
     std::copy(data.begin(), data.end(), this->data); 
    } 

    Vector(T(&data)[SIZE]) { 
     std::copy(data, data + SIZE, this->data); 
    } 

protected: 
#pragma pack(push, 1) //stores the alignment of aggregate types and sets it to 1 byte 
    union { 
     struct { 
      T x, y, z, w; 
     }; 
     T data[SIZE]; 
    }; 
#pragma pack(pop) //restore old data alignment 
}; 

template<typename T> 
struct Vector2 : public Vector<T, 2> { 
    using Vector<T, 2>::Vector<T, 2>; 

    Vector2(T x = 0, T y = 0) : 
     Vector({ x, y }){} 

    Vector2(const Vector& vec) : 
     Vector(vec) {} 

    using Vector::x; 
    using Vector::y; 
}; 

int main() { 
    double floats[2]{ 2, 3 }; 
    Vector2<double> v{ floats }; 
    Vector<double, 2> c{ 5., 6. }; 

    std::cout << "v.x = " << v.x; 
    //Is oke, v.x is visible here because of the public using statement 

    std::cout << " c.x = " << c.x << "\n"; 
    //Is not oke, c is not a Vector2<double>. It is a Vector<double, 2> so its member x is protected and thus not visible from here. 
} 

輸出:v.x = 2 c.x = 5

所以這個方案不僅成功地編譯和鏈接,但它也運行並打印敏感數據。 我嘗試將c更改爲Vector<double, 3>,但這並沒有改變任何內容。此外,成員zw也可以看到,就像xy一樣。但是,data不可見(例如,std::cout << c.data[0];不會按預期進行編譯)。

智能感知比在這種情況下,聰明的編譯器,因爲它成功地檢測到錯誤,並抱怨它。

我使用的Visual Studio 2013

PS:

方問題:我找到的編譯器的另一個怪癖在這相同的代碼段。如果我更改以下行:

using Vector<T, 2>::Vector<T, 2>; 

到:

using Vector<T, 2>::Vector; 

我得到這個編譯器錯誤:error C2886: 'Vector<T,0x02>' : symbol cannot be used in a member using-declaration

如果我將其更改爲:

using Vector::Vector; 

編譯器崩潰全部與:fatal error C1001: An internal error has occurred in the compiler. see reference to class template instantiation 'Vector2<T>' being compiled

這(它例如崩潰的事實)可能只是在編譯器中的錯誤,但是,如果有人知道,我還是想知道爲什麼既不是該行編譯兩個替代形式。

回答

2

我不得不做一些更改,以便在clang上編譯代碼。看來,visual C++是非常寬容的,並允許非法(或我應該說非標準)的語法。

這裏是校正程序:

#include <iostream> 
#include <algorithm> 

template<typename T, size_t SIZE> 
struct Vector { 
    Vector(std::initializer_list<T> data) { 
     std::copy(data.begin(), data.end(), this->data); 
    } 

    Vector(T(&data)[SIZE]) { 
     std::copy(data, data + SIZE, this->data); 
    } 

protected: 
#pragma pack(push, 1) //stores the alignment of aggregate types and sets it to 1 byte 
    union { 
     struct { 
      T x, y, z, w; 
     }; 
     T data[SIZE]; 
    }; 
#pragma pack(pop) //restore old data alignment 
}; 

template<typename T> 
struct Vector2 : public Vector<T, 2> { 
    using Vector<T, 2>::Vector; 

    Vector2(T x = 0, T y = 0) : 
    Vector<T, 2>({ x, y }){} 

    Vector2(const Vector2& vec) : 
    Vector<T, 2>(vec) {} 

    using Vector<T, 2>::x; 
    using Vector<T, 2>::y; 
}; 

int main() { 
    double floats[2]{ 2, 3 }; 
    Vector2<double> v{ floats }; 
    Vector<double, 2> c{ 5., 6. }; 

    std::cout << "v.x = " << v.x; 
    //Is oke, v.x is visible here because of the public using statement 

    std::cout << " c.x = " << c.x << "\n"; 
    //Is not oke, c is not a Vector2<double>. It is a Vector<double, 2> so its member x is protected and thus not visible from here. 
} 

這裏是修改後的(預期)錯誤:

./vec.cpp:66:33: error: 'x' is a protected member of 'Vector<double, 2>' 
    std::cout << " c.x = " << c.x << "\n"; 
           ^
./vec.cpp:37:15: note: declared protected here 
      T x, y, z, w; 
      ^
1 error generated.