2

I have a fairly bog standard Vector4 struct (the math kind not the C++ kind) which is a POD and is templated:


template<typename T>
struct Vector4 {
    T x, y, z, w;

    Vector4 operator+(const Vector4& other) const { return Vector4{ x + other.x, y + other.y, z + other.z, w + other.w }; }
    Vector4 operator-(const Vector4& other) const { return Vector4{ x - other.x, y - other.y, z - other.z, w - other.w }; }
    Vector4 operator*(const Vector4& other) const { return Vector4{ x * other.x, y * other.y, z * other.z, w * other.w }; }
    Vector4 operator/(const Vector4& other) const { return Vector4{ x / other.x, y / other.y, z / other.z, w / other.w }; }
    Vector4 operator+(const T& a) const { return Vector4{ x + a, y + a, z + a, w + a }; }
    Vector4 operator-(const T& a) const { return Vector4{ x - a, y - a, z - a, w - a }; }
    Vector4 operator*(const T& a) const { return Vector4{ x * a, y * a, z * a, w * a }; }
    Vector4 operator/(const T& a) const { return Vector4{ x / a, y / a, z / a, z / a }; }

    Vector4& operator+=(const Vector4& other) { x += other.x; y += other.y; z += other.z; w += other.w; return *this; }
    Vector4& operator-=(const Vector4& other) { x -= other.x; y -= other.y; z -= other.z; w -= other.w; return *this; }
    Vector4& operator*=(const Vector4& other) { x *= other.x; y *= other.y; z *= other.z; w *= other.w; return *this; }
    Vector4& operator/=(const Vector4& other) { x /= other.x; y /= other.y; z /= other.z; w /= other.w; return *this; }
    Vector4& operator+=(const T& a) { x += a; y += a; z += a; w += a; return *this; }
    Vector4& operator-=(const T& a) { x -= a; y -= a; z -= a; w -= a; return *this; }
    Vector4& operator*=(const T& a) { x *= a; y *= a; z *= a; w *= a; return *this; }
    Vector4& operator/=(const T& a) { x /= a; y /= a; z /= a; w /= a; return *this; }

    T& operator[](size_t index) { return *(reinterpret_cast<T*>(this) + index); }
};

using Vector4f = Vector4<float>;
using Vector4i = Vector4<int>;
using Vector4i32 = Vector4<int32_t>;
using Vector4ui32 = Vector4<uint32_t>;
using Vector4i64 = Vector4<int64_t>;
using Vector4ui64 = Vector4<uint64_t>;

The problem I am having is that I cant make a std::vector of my Vector4 class. When I try the following:

std::vector<ogl::Vector4f> vec;
vec.emplace_back(1.0f, 2.0f, 3.0f, 4.0f);

I get this compile error

'Vector4::Vector4': no overloaded function takes 4 arguments

I have my own vector (C++ kind not math kind) class that I use and I tried using emplace_back with it but I got the same error. I also tried using and not using allocators (in my custom vector class) and have tried almost everything under the sun!

I can fix this issue by defining a constructor, but then it doesn't become a POD anymore. Normal construction using brace initialization works fine so I don't what's wrong.

If anyone can explain why this is happening/how to fix this (or if this is normal behaviour) it would be most appreciated.

obwan02
  • 113
  • 10
  • Compiler in gcc and MSVC; errors in clang - live (note C++20 required) - https://godbolt.org/z/TaTc8fo1q Perhaps add [language-lawyer] as we have compiler differences ? – Richard Critten Sep 26 '21 at 11:00

1 Answers1

3

emplace_back uses parentheses to initialize the value, which means a constructor is required to use it until C++20. C++20 introduced parenthesized initialization of aggregates, so you code becomes valid as is.

Until then you can just do

vec.push_back({1.0f, 2.0f, 3.0f, 4.0f});
yuri kilochek
  • 12,709
  • 2
  • 32
  • 59