член, определенный в анонимной структуре в защищенном анонимном объединении, все еще публично виден

Мне удалось скомпилировать и запустить 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> но это ничего не изменило. Также участники z а также w видны так же, как x а также y являются. Тем не мение, data не виден (например, std::cout << c.data[0]; не скомпилируется, как ожидалось).

В этом случае Intellisense умнее компилятора, так как он успешно обнаруживает ошибку и жалуется на нее.

я использую Визуальная студия 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,

Это (например, тот факт, что он дает сбой), вероятно, является просто ошибкой в ​​компиляторе, но, если кто-нибудь знает, мне все равно хотелось бы знать, почему ни одна из двух альтернативных форм этой строки не компилируется.

0

Решение

Мне пришлось внести некоторые изменения, чтобы код компилировался на 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.
3

Другие решения

Других решений пока нет …