Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constants defined in template classes [duplicate]

Possible Duplicate:
GCC problem : using a member of a base class that depends on a template argument

I thought I was familiar with C++, but apparently not familiar enough.
The problem is when you define a constant in a template class, you can use the constant in new classes that derive from that class, but not new template classes that derive from it.

For example, gcc says

test.h:18: error: ‘theconstant’ was not declared in this scope

when I try to compile this (simplified) header file:

#pragma once

template <typename T> class base
{
  public:
    static const int theconstant = 42;
};

class derive1 : public base<size_t>
{
  public:
    derive1(int arg = theconstant) {}
};

template<typename T> class derive2 : public base<T>
{
  public:
    derive2(int arg = theconstant) {} // this is line 18
};

So the problem is that one class, derive1, compiles fine, but the other class, derive2, which is a template specialisation, does not.
Now maybe gcc's error is not clear enough, but I don't understand why the constructor in derive2 would have a different scope than the one in derive1.
In case it matters, this happens during compilation of the header file itself, not when instantiating an object of type derive2<type>.

I also know what to change to make this compile, so I'm not really looking for one-line pieces of code as answers. I want to understand why this happens! I tried searching the web, but apparently I'm not using the correct search arguments.

like image 813
Mr Lister Avatar asked Jul 01 '12 21:07

Mr Lister


2 Answers

I am pretty sure this will help you understand:

Your code which does not compile:

template<typename T> class derive2 : public base<T>
{
  public:
    derive2(int arg = theconstant) {} // this is line 18
};

And the reason why:

template <> class base<size_t>
{
  public:
    static const int ha_idonthave_theconstant = 42;
};
derive2<size_t> impossible_isnt_it; 

The specialization!!! Compiler at your line 18 cannot be sure that you will not specialize the base<> in the way that this constant will not be present there at all.

like image 161
PiotrNycz Avatar answered Nov 19 '22 04:11

PiotrNycz


Try

template<typename T> class derive2 : public base<T>
{
  public:
    derive2(int arg = base<T>::theconstant) {} // this is line 18
};

Basically you've specified the incomplete scope for the "theconstant".

like image 29
Viktor Latypov Avatar answered Nov 19 '22 03:11

Viktor Latypov