c++ - 在 protected 匿名 union 中的匿名结构中定义的成员仍然公开可见

标签 c++ c++11 visual-studio-2013 unions anonymous-inner-class

我已经设法编译并运行了 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>但这并没有改变任何东西。还有成员(member)zw就像x一样可见和 y是。然而,data不可见(例如 std::cout << c.data[0]; 不会按预期编译)。

在这种情况下,Intellisense 比编译器更聪明,因为它成功检测到错误并提出错误。

我正在使用 Visual Studio 2013

附言:

附带问题:我在同一代码片段中发现了编译器的另一个怪癖。如果我更改以下行:

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++ - 在 protected 匿名 union 中的匿名结构中定义的成员仍然公开可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33780845/

相关文章:

c++ - 如何找到 SQLWCHAR 的长度?

c++ - 对于构造函数,{} 是否与 =default 相同?

c++ - 如何修复模板内的错误重构 decltype

c++ - 为什么 std::for_each + lambda 没有按预期工作?

visual-studio - visualstudio.vnext (14) ctp 和 vs2013 并排

c# - 为什么 VS2015RC 说 "The ViewBag doesn' t 存在于当前上下文中”,而 VS2013 说没有错误?

c++ - 我可以将 C++ 项目转换为 Delphi 吗?

c++ - 如何更改另一个进程的内存空间中的值

c++ - LNK 2019试图链接DLL和EXE

C++ 在声明和定义之间拆分默认参数值