Мне удалось скомпилировать и запустить 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
,
Это (например, тот факт, что он дает сбой), вероятно, является просто ошибкой в компиляторе, но, если кто-нибудь знает, мне все равно хотелось бы знать, почему ни одна из двух альтернативных форм этой строки не компилируется.
Мне пришлось внести некоторые изменения, чтобы код компилировался на 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.
Других решений пока нет …