Reputation: 6194
I have a code which consists of three layers. At the highest level there is a Master class. Then there is a Grid class, that knows the Master, since it uses its functions for general tasks. On a Grid, I can create Fields, which take the Grid as an argument in its constructor. Now, I would like to make both Grid and Field templates, to enable them to contain arbitrary data types.
I don't manage to let Field handle the type that has been given to Grid correctly. In principle he should be able to deduce it. How do I make this work? My example, of course, does not compile yet.
#include <vector>
class Master
{
public:
Master() {};
};
template<class T>
class Grid
{
public:
Grid(Master &masterin) : master(masterin) {};
private:
Master &master;
std::vector<T> data;
};
template<class T>
class Field
{
public:
Field(Master &masterin, Grid &gridin) : master(masterin), grid(gridin) {};
private:
Master &master;
Grid &grid;
std::vector<T> data;
};
int main()
{
Master master;
Grid<int> grid(master);
Field<double> field(master, grid);
return 0;
}
Upvotes: 0
Views: 149
Reputation: 171433
template<class T>
class Field
{
public:
Field(Master &, Grid &);
This is not valid, you cannot pass an argument of type Grid
because Grid
is not a type
private:
Master &master;
Grid &grid;
You cannot have a member of type Grid
because it is not a type
You can fix the constructor by making it a template:
template<typename U>
Field(Master &, Grid<U> &);
This will accept any type that is a specialization of the Grid
template, but you still can't have a member variable of a template, you need to decide what kind of Grid
you want the member to be, or store it in a flexible type like boost::any
.
If you want Field
to be able to work with any kind of Grid
then it needs another template parameter:
template<class T, class U>
class Field
{
public:
Field(Master&, Grid<U>&);
private:
Master& master;
Grid<U>& grid;
std::vector<T> data;
};
To deduce the type of Grid<U>
you can define a generator function:
template<typename T, typename U>
Field<T, U>
make_field(Master& m, Grid<U>& g)
{ return Field<T, U>(m, g); }
Master master;
Grid<int> grid;
auto field = make_field<double>(master, grid); // returns Field<double, int>
However, without C++11's auto
keyword that is inconvenient to use and doesn't really help much as you have to spell out the full type anyway:
Field<double, int> field = make_field<double>(master, grid);
Upvotes: 3
Reputation: 147036
Grid is a template, so it must have a template argument to be useful here. Given your example, it seems that you want Grid and Field to have independent types. This means that Field must be templatized with two parameters- one for itself and one for the Grid it works with.
Upvotes: 1