在受保护的匿名联合中的匿名结构中定义的成员仍然公开可见
member defined in anonymous struct in protected anonymous union is still publicly visible
我已经设法编译和 运行 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
因此该程序不仅成功编译 link,而且 运行 并打印出合理的数据。
我尝试将 c
的类型更改为 Vector<double, 3>
但这并没有改变任何东西。此外,成员 z
和 w
与 x
和 y
一样可见。但是,data
不可见(例如,std::cout << c.data[0];
不会按预期编译)。
在这种情况下,Intellisense 比编译器更聪明,因为它成功检测到错误并提出错误。
我正在使用 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
。
这(例如它崩溃的事实)可能只是编译器中的一个错误,但如果有人知道,我仍然想知道为什么该行的两种替代形式都无法编译。
我必须进行一些更改才能让代码在 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.
我已经设法编译和 运行 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
因此该程序不仅成功编译 link,而且 运行 并打印出合理的数据。
我尝试将 c
的类型更改为 Vector<double, 3>
但这并没有改变任何东西。此外,成员 z
和 w
与 x
和 y
一样可见。但是,data
不可见(例如,std::cout << c.data[0];
不会按预期编译)。
在这种情况下,Intellisense 比编译器更聪明,因为它成功检测到错误并提出错误。
我正在使用 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
。
这(例如它崩溃的事实)可能只是编译器中的一个错误,但如果有人知道,我仍然想知道为什么该行的两种替代形式都无法编译。
我必须进行一些更改才能让代码在 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.