Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ typedef with nested templates is not a class, struct, or union type

I'm not sure to understand why the following code is not compiled with g++:

t.cpp: In instantiation of ‘Distrib<double>’:
t.cpp:28:56:   instantiated from ‘Sampler<Distrib<Solution<double> > >’
t.cpp:35:48:   instantiated from here
t.cpp:16:45: erreur: ‘double’ is not a class, struct, or union type
t.cpp:18:43: erreur: ‘double’ is not a class, struct, or union type

I was expecting to be able to propagate the AtomType type across the nested templates…

#include <iostream>
#include <vector>

template<typename T>
class Solution
{
    public:
        typedef T AtomType;
};

template<typename SOLT>
class Distrib
{
    public:
        typedef typename SOLT::AtomType AtomType;
        typedef std::vector<AtomType> Matrix;

        Matrix matrix;
};

template<typename DT>
class Sampler
{
    public:
        typedef typename DT::AtomType AtomType;
        typedef typename Distrib<AtomType>::Matrix Matrix;

        Matrix matrix;
};

int main()
{
    Sampler< Distrib< Solution<double> > > sampler;
}
like image 870
nojhan Avatar asked Jul 10 '12 09:07

nojhan


3 Answers

In your Distrib template you have the following typedef

typedef typename SOLT::AtomType AtomType;

Which means that any type you pass in as a template parameter, must have a AtomType as a member, and double has no such thing.

If you made a class like so

class Double
{
   typedef myType AtomType;
};

and passed that in as a template parameter to your Distrib template, it would compile, as Double::AtomType does exist.

like image 129
Tony The Lion Avatar answered Nov 24 '22 00:11

Tony The Lion


In your Sampler class, you have:

typedef typename Distrib<AtomType>::Matrix Matrix;

Here, AtomType is double, so this is

typedef typename Distrib<double>::Matrix Matrix;

And then in your Distrib class, the line

typedef typename SOLT::AtomType AtomType;

expands to

typedef typename double::AtomType AtomType;

Hence the error message. I think you want the line in the Sampler class to be:

typedef typename DT::Matrix Matrix;
like image 33
TonyK Avatar answered Nov 24 '22 00:11

TonyK


The Matrix typedef in the Distrib class is using AtomType, but what we would expect was a DT:

typedef typename Distrib<DT>::Matrix Matrix;

The compiler was seeing the double propagated across nested templates.

like image 40
nojhan Avatar answered Nov 24 '22 01:11

nojhan