Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use an #if directive with a template non-type argument? (Vector all-in-one class)

Tags:

c++

I am creating a Vector class and instead of creating separate classes for Vector2, Vector3 and Vector4 I want to make an all-in-one class. My problem is that I want to define certain properties depending on the size of the vector. For example, a vector of size 2 will have an x and y component, but not a z component.

I'm attempting to use the #if directive to check the non-type template argument (SIZE) to create properties depending on the size of the vector. I did some research and I don't think it's possible this way. I'm wondering if anyone has an idea about how to achieve want I want?

template <typename T, int SIZE>
class Vector
{
public:
    union
    {
        struct
        {
#if SIZE == 2
            T x, y;
#endif
#if SIZE == 3
            T z;
#endif
#if SIZE == 4
            T w;
#endif
        };
        T data[SIZE];
    };
};

I want to be able to create and access a Vector like so:

Vector<int, 2> vec2;
vec2.x;
Vector<int, 3> vec3;
vec3.z;

Any feedback is appreciated!

EDIT: After reviewing the comments I came up with a nifty solution... Hopefully it works for me. I created a templated class:

template <typename T, unsigned int SIZE> class _vec;

This deals with the data (components) of the vector and contains the behaviour. Then I made another templated class that will sort of specialise _vec like so:

template <typename T, unsigned int SIZE> class Vector : public _vec<T, SIZE>;

This is a vector of any size. Now I can specialise that for Vector2, Vector3 and Vector4:

template <typename T> class Vector<T, 2> : public _vec<T, 2>;

template <typename T>
using Vector2 = Vector<T, 2>;

I'll let you know how HORRIBLE this will turn out... ;P

EDIT 2: It worked, but didn't work out... :(

like image 322
Davinatoratoe Avatar asked Jan 21 '26 03:01

Davinatoratoe


1 Answers

No, this is not possible.

In the phases of translation, the preprocessing phase comes before the template instantiation phase. So in this case, you will end up having none of the variables defined in the template Vector because SIZE is not defined at the preprocessing phase.

As per the C++ standard, [cpp.cond]/9:

After all replacements due to macro expansion and evaluations of defined-macro-expressions and has-include-expressions have been performed, all remaining identifiers and keywords, except for true and false, are replaced with the pp-number 0, and then each preprocessing token is converted into a token.

So the value of SIZE here will be 0 and thus none of the conditions of the conditional inclusions are met.

You can instead specialize your template to have different variables for different instantiations.

like image 179
P.W Avatar answered Jan 22 '26 17:01

P.W



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!