Lagf
Lagf

Reputation: 123

C++ template static const member variable in template class

I am trying to implement a vector (in the math sense) using templates. I would like to define standard vector constants in the class. I managed to do it for simple constants (all zeroes, all ones) but I am now struggling to define the more difficult unit vectors (all zeroes except one component set to one at given index).

I did not yet find an elegant way to do that. Here is how I would like to define that:

#include <iostream>

template<unsigned int tSize, typename tReal>
class Vector {
public:

    template<unsigned int tIndex>
    static const Vector msUnit;

    inline Vector () {}

    template<typename...tTypes>
    inline Vector (tTypes...pVals) {
        set(mReals, pVals...);
    }

    inline tReal operator[] (unsigned int pIndex) {
        return mReals[pIndex];
    }

    inline const tReal operator[] (unsigned int pIndex) const {
        return mReals[pIndex];
    }

protected:

    template<typename tType>
    void set (tReal* pPtr, const tType pVal) {
        *pPtr = pVal;
    }

    template<typename tType, typename...tTypes>
    void set (tReal* pPtr, const tType pVal, const tTypes...pVals) {
        *pPtr = pVal;
        set(pPtr+1, pVals...);
    }

    tReal mReals [tSize];

};

int main() {

    Vector<3,double> lVec = Vector<3,double>::msUnit<2>;

    std::cout << "Vector: (" << lVec[0] << ", " << lVec[1] << ", " << lVec[2] << ")" << std::endl;

    return 0;
}

But I have not found a way to define the msUnit static const member template.

I tried this:

    template<unsigned int tIndex, unsigned int tSize, typename tReal>
    const Vector<tSize,tReal> Vector<tSize,tReal>::msUnit<tIndex>;

But compilers (clang & gcc) complain:

prog.cc:43:48: error: nested name specifier 'Vector<tSize, tReal>::' for declaration does not refer into a class, class template or class template partial specialization
const Vector<tSize,tReal> Vector<tSize,tReal>::msUnit<tIndex>;
                          ~~~~~~~~~~~~~~~~~~~~~^
prog.cc:43:54: error: expected ';' at end of declaration
const Vector<tSize,tReal> Vector<tSize,tReal>::msUnit<tIndex>;
                                                     ^
                                                     ;
prog.cc:43:54: error: expected unqualified-id

Here is a live example of this test: http://melpon.org/wandbox/permlink/AzbuATU1lbjXkksX

Is it even possible to have static const template variable members in template classes ? And if so how ?

And I still have to find a way to provide an initializer for the msUnit template.

Upvotes: 2

Views: 2530

Answers (1)

overseas
overseas

Reputation: 1731

You already found the way how you can decleare your msUnit - you have to use two templates, i.e.

template<unsigned tSize, typename tReal>
template<unsigned tIndex>
const Vector<tSize, tReal> Vector<tSize, tReal>::msUnit;

As you have currently no matching constructor for initializing the n'th argument to one and all others to zero (which wouldn't make sense I guess), you can just use your own function. As you already access a static member of your class, you also have access to your complete class, so you can just use

template<unsigned int tSize, typename tReal>
class Vector {
public:
    // ...

    template<unsigned int tIndex>
    static const Vector msUnit;

private:
    static const Vector<tSize, tReal> createUnitVector(unsigned tIndex) {
        Vector<tSize, tReal> v{};
        v.mReals[tIndex] = tReal(1);
        return v;
    }

    tReal mReals [tSize];
};

template<unsigned tSize, typename tReal>
template<unsigned tIndex>
const Vector<tSize, tReal> Vector<tSize, tReal>::msUnit{Vector::createUnitVector(tIndex)};

So everything as you already have it, but you initialize your vector with some other function given in your class.

Here you go for the live demo: http://melpon.org/wandbox/permlink/5b7cgXTeqXZDoCRp

Upvotes: 3

Related Questions