using an inherited typedef?

So why can't I use "Index" as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template <typename T>
class base
{
 public:
  typedef int Index;
};

template <typename T>
class child:
public base<T>
{
 public:
  using typename base<T>::Index;

  Index i;
};

int main()
{
 child<int> c;
 return 0;
}
KarlisRepsons wrote:
So why can't I use "Index" as follows:


I don't know to be honest but I have always used this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
template <typename T>
class base
{
 public:
  typedef int Index;
};

template <typename T>
class child:
public base<T>
{
 public:
//  using typename base<T>::Index;
  typedef typename base<T>::Index Index;

  Index i;
};

int main()
{
 child<int> c;
 return 0;
}
Well according to this:

Cpp03 Standard wrote:
A using-directive shall not appear in class scope, but may appear in namespace scope or in block scope.


It looks like the compiler should have given an error on line 13 because the using directive should not appear in class scope...
Last edited on
That's news to me!

I've seen this like a million times:

1
2
3
4
5
6
7
8
9
10
class Parent
{
  void Function();
};

class Child : public Parent
{
  void Function(int v);  // hides Parent::Function
  using Parent::Function;  // unhides it
};
Out of curiosity what does the following using declaration effect?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Parent
{
  void Function();
};

class Child : public Parent
{
  void Function(int v);  // hides Parent::Function
  using Parent::Function;  // unhides it

  void other_func()
  {
    Function(1); // Parent or Child?
  }

  void and_again();
};

void Child::and_again()
{
  Function(2); // Parent or Child?
}


Last edited on
It's more like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Parent
{
  void Function();
};

class Child : public Parent
{
  void Function(int v);  // hides Parent::Function
  using Parent::Function;  // unhides it

  void other()
  {
    Function(1);  // Child::Function
    Function();  // errors without using directive.  "No matching call to Function"
        // with the using directive, it calls Parent::Function
  }
};
Ah okay. Further investigation has revealed that I was confusing a 'using declaration' with a 'using directive'.
Last edited on
Function overloading doesn't work across class boundaries, it does work across namespace boundaries.

However with "using" this works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

using namespace std;

struct base
{
  void f() {cout << " base::f() " << endl;}
  void f(float) {cout << " base::f(float) " << endl;}
  void f(double) {cout << " base::f(double) " << endl;}
};

struct child:
public base
{
  void f(int) {cout << " child::f(int) " << endl;}
  using base::f;

  void test()
  {
   f();
   f(1);
   f(2.f);
   f(3.);
  }
};

int main()
{
 child c;
 c.test();
 return 0;
}


On the previous problem: looks like I'll have to use that second typedef approach. Maybe it's even not different from the result of using declaration, if it would work?
Ah okay. Further investigation has revealed that I was confusing a 'using declaration' with a 'using directive'.


For the record, which one is which? I always get those mixed up, as well.
directive --> using namespace X;
declaration --> using X::element;

Add: still I would appreciate if anyone explains about using typedef...
Last edited on
I don't use using very much so I didn't know there was a difference. So I only checked with the standard for a 'using directive'.

Here is what it has to say:

cpp03 Standard wrote:
7.3.3 The using declaration
A using-declaration introduces a name into the declarative region in which the using-declaration appears. That name is a synonym for the name of some entity declared elsewhere.

using-declaration:
using typename opt ::opt nested-name-specifier unqualified-id ;
using :: unqualified-id ;



cpp03 Standard wrote:
7.3.4 Using directive

using-directive:
using namespace ::opt nested-name-specifieropt namespace-name ;

A using-directive shall not appear in class scope, but may appear in namespace scope or in block scope.
[Note: when looking up a namespace-name in a using-directive, only namespace names are considered, see 3.4.6. ]

A using-directive specifies that the names in the nominated namespace can be used in the scope in which
the using-directive appears after the using-directive. During unqualified name lookup (3.4.1), the names
appear as if they were declared in the nearest enclosing namespace which contains both the using-directive
and the nominated namespace. [Note: in this context, “contains” means “contains directly or indirectly”. ]

A using-directive does not add any members to the declarative region in which it appears.
Last edited on
KarlisRepsons wrote:
Add: still I would appreciate if anyone explains about using typedef.


cpp03 Standard wrote:
7.1.3 The typedef specifier
Declarations containing the decl-specifier typedef declare identifiers that can be used later for naming
fundamental (3.9.1) or compound (3.9.2) types. The typedef specifier shall not be used in a function-
definition (8.4), and it shall not be combined in a decl-specifier-seq with any other kind of specifier except

a type-specifier.

typedef-name:
identifier

A name declared with the typedef specifier becomes a typedef-name. Within the scope of its declaration,
a typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier in
the way described in clause 8. A typedef-name is thus a synonym for another type. A typedef-name does
not introduce a new type the way a class declaration (9.1) or enum declaration does.



I think the relevant part is: "A typedef-name is thus a synonym for another type. "
Last edited on
I have to come back: in effect, where I have a line
typedef HashIteratorBase<Key, T, Slots, Compare, Hash> HIB;
, I should have a using declaration, so (maybe..) I would have a real synonym, which doesn't produce a compiler error in a particular use case (makes Base::X exactly the same as Deri::X, while has to be defined just in Base).

After all this appears to be an old defect in C++ itself. You can start at [1] to find out more. It reference a huge text-load, so I'm still wondering if this fix will ever get into a C++ standard.

By the way, the fragment I posted compiles fine on some other compilers.

[1] http://stackoverflow.com/questions/1071119/c-accessing-types-from-dependent-base-classes
Topic archived. No new replies allowed.