user2826735
user2826735

Reputation: 305

c++: defining variable-length array within a class using templates

I am trying to build a class MapV2. In the class, I would like to have an array of Cell objects as a private member (Cell is another class). I am trying to get it so that the size of the map is assigned by a template parameter used with the constructor. I.e, I am trying to get something similar to the following:

const size_t arraySize = 12;
MapV2<arraySize> myMapV2;

Here is my file Map.h:

#pragma once
#include <iostream>
#include "Cell.h"

template<size_t M, size_t N>
class MapV2
{

public:
    MapV2();
    ~MapV2();
private:
    Cell myMapV2[M*N];
};

Here is Map.cpp:

#include <iostream>
#include "MapV2.h"

MapV2<size_t M, size_t N>::MapV2()
{

}

MapV2::~MapV2()
{

}

And here is the main function:

int main()
{
    const size_t xLength = 6;
    const size_t yLength = 8;
    MapV2 <xLength, yLength> Example;
    return 0;
}

But when I try to compile, I get the following mess of errors:


Compiling: MapV2.cpp
D:\Users\Vik\ModSim1a\MapV2.cpp:4: error: wrong number of template arguments (1, should be 2)

D:\Users\Vik\ModSim1a\MapV2.h:7: error: provided for 'template<unsigned int M, unsigned int N> class MapV2'

D:\Users\Vik\ModSim1a\MapV2.cpp: In function 'int MapV2()':
D:\Users\Vik\ModSim1a\MapV2.cpp:4: error: 'int MapV2()' redeclared as different kind of symbol

D:\Users\Vik\ModSim1a\MapV2.h:7: error: previous declaration of 'template<unsigned int M, unsigned int N> class MapV2'

D:\Users\Vik\ModSim1a\MapV2.cpp:7: warning: no return statement in function returning non-void

D:\Users\Vik\ModSim1a\MapV2.cpp: At global scope:
D:\Users\Vik\ModSim1a\MapV2.cpp:9: error: expected constructor, destructor, or type conversion before '::' token

Process terminated with status 1 (0 minutes, 0 seconds)
5 errors, 1 warnings

I have Googled this problem and have spent some time trying to follow the advice given in similar StackOverflow posts, however none of the examples told what to do in the code for the actual constructor (i.e. the MapV2.cpp file) to get this to work. I feel like there is an easy fix for these errors. Any help is much appreciated.

Upvotes: 6

Views: 1390

Answers (1)

user1508519
user1508519

Reputation:

See Why can templates only be implemented in the header file? for more information. If you try to alleviate the problem using explicit instantiation, your template parameters are non-types and so they will have to look like this:

template class MapV2<6, 8>; //et. all for all possible number combinations

If you try this:

template class MapV2<size_t, size_t>;
// or this, replace unsigned long int with what size_t is on your system
template class MapV2<unsigned long int, unsigned long int>;

You will get this mind-boggling error:

error:   expected a constant of type ‘long unsigned int’, got ‘long unsigned int’

That's because it expects a long unsigned int and not the type.

You can see why this would be a problem. I would move the definition of your constructors into the header to avoid headaches.

struct Cell {};

template<size_t M, size_t N>
class MapV2
{

public:
    // Declaration
    MapV2();
    ~MapV2();
private:
    Cell myMapV2[M*N];
};

// Definition
template<size_t M, size_t N>
MapV2<M, N>::MapV2()
{

}

template<size_t M, size_t N>
MapV2<M, N>::~MapV2()
{

}

Upvotes: 2

Related Questions