GivAlz
GivAlz

Reputation: 185

C++ template explicit declaration of member function value/ avoiding the problem with macros

I thought this was going to be easier; I have a class of this sort:

template <int dim, int spacedim>
class FE_problem
{
    //...
   void generate_mesh();
}

I have a particular request for that one member function, generate_mesh: I need it to be explicitly different depending on the value of dim and spacedim.

I made several attempts such as:

template <int dim, int spacedim>
void FE_problem<1, 3>::generate_mesh()
{
...do a kind of mesh initialization ...
}

template <int dim, int spacedim>
void FE_problem<3, 3>::generate_mesh()
{
...do another kind of mesh initialization ...
}

But couldn't make it compile.

I tried using std::enable_if, but I still don't understand well enough how it works, and I don't know if it is the right way.

To avoid (for now) the problem I've tried with macros, using the following code when defining the method:

#if DIM 1
template <int dim, int spacedim>
void FE_problem<dim,spacedim>::generate_mesh()
{
...do a kind of mesh initialization ...
}
#elif DIM 3
template <int dim, int spacedim>
void FE_problem<dim,spacedim>::generate_mesh()
{
...do another kind of mesh initialization ...
}
#endif

And then, when initializing the class in the main function, I tried something like:

#define DIM 1
auto FE1 = FE_problem<1, 3>();
#undef DIM

#define DIM 3
auto FE2 = FE_problem<1, 3>();
#undef DIM

In the hope the preprocessor would do the right substitutions, but the result is that DIM results not defined (in both cases). Is this because of the order in which the preprocessor is substituting DIM? Is there a fix for this?

Upvotes: 0

Views: 58

Answers (1)

NathanOliver
NathanOliver

Reputation: 180935

You almost have it. When you specialize the template, and it is not a partial specialization, you don't include any template parameters. Doing that would make the code look like

template <int dim, int spacedim>
class FE_problem
{
public:
   void generate_mesh();
};

template <> // full specialization, leave template parameter blank as they are provided below
void FE_problem<1, 3>::generate_mesh()
//              ^^^^ specify the specialized types/values here  
{
    std::cout << "void FE_problem<1, 3>::generate_mesh()\n";
}

template <> // full specialization, leave template parameter blank as they are provided below
void FE_problem<3, 3>::generate_mesh()
//              ^^^^ specify the specialized types/values here  
{
    std::cout << "void FE_problem<3, 3>::generate_mesh()\n";
}

int main()
{
    FE_problem<1, 3>{}.generate_mesh();
    FE_problem<3, 3>{}.generate_mesh();
}

Which outputs

void FE_problem<1, 3>::generate_mesh()
void FE_problem<3, 3>::generate_mesh()

Upvotes: 3

Related Questions