Accessing inherited template functions

Hi,

I am having some issues trying to access an inherited template class how I would like to. I have written out a simplified case of mine for completeness and to focus on the main issue.

This is my base class, Bar, whose functions I want access to.
1
2
3
4
5
6
7
8
9
10
11
//Bar.h
#include <iostream>

class Bar {
public:
  Bar(){}
  ~Bar(){}

  DoSomething(){ std::cout << "Doing Something " << std::endl; }

};



// Template class which inherits Bar (when specified), obviously I will have
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Foo.h
#include <iostream>

template< class U >
Foo : public U {

public:
  Foo(){}
  ~Foo(){}

  DoSomethingElse { std::cout << "Doing Something Else " << std::endl; }
  
  Bar::DoSomething(); //What I have to do
  DoSomething(); //What I want to do

};


In Foo, if I try and access Bar's "DoSomething()" function, I have to use "Bar::DoSomething()". Is it possible to access it simply as DoSomething() from Foo. This is because I want to be able to access DoSomething() from my main program, as shown below.

1
2
3
4
5
6
7
//main.cpp
#include "foo.h"
int main(void) {
  Foo<Bar> foo;
  foo.DoSomethingElse(); //OK
  foo.DoSomething();     //What I want to be able to access as well
}



Thanks in advance.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Bar
{
public:
    void DoSomething() {}
};

template <typename T>
class Foo :public  T 
{

public:
    void DoSomeMore()
    {
        DoSomething(2); //Won't pass Template syntax check - See Note 1
		
		T t;
        DoSomething(t); //Will pass template syntax check - See Note 2 
		
		T::DoSomething(4); //Will pass template syntax check - See Note 2 
    }
};


The reasoning go something like this:
Note 1.
The DoSomething(2) function call does NOT depend
on any of the Foo template parameters ( in other words the template parameter T is not involved)
Therefore it is a standard C++ function call - which means that the function itself or
the declaration MUST already be known.
Given That Foo itself does not contain the function, and the base class type is NOT known
at this time because the base class depends on the template parameter T,
then we get the error.

Note 2.
Both these function calls invlve the template parameter T.
Although T is not resolved at the initial template checks, their syntax is correct
so they will pass the template syntax checks.
However, when you try to instatntiate an actual concrete version
of Foo - they could well fail depending on what type T turns out to be.

1
2
3
4
5
6
Foo<int> fi;  //complete failure - cannot be instatiated at all.
Foo<std::string>fs ; //will instantiate OK - but
fs.DoSomeMore(); //compile time failure on any of the 3 function calls

 Foo<Bar>fb;  //instantiate ok
fb.DoSomeMore(); //will only work for T::DoSomething(4), compile time error on other 2; 


EDIT
I really should mention the using declaration and class members
to resolve some of the problems - so I'll update later.
Last edited on
> In Foo, if I try and access Bar's "DoSomething()" function, I have to use "Bar::DoSomething()".
> Is it possible to access it simply as DoSomething()

In a template that we write, there are two kinds of names (identifiers) that could be used - dependant names and non- dependant names. Quite unsurprisingly, a dependant name is a name that depends on a template parameter; a non- dependant name has the same meaning irrespective of what the template parameters are. For example:
1
2
3
4
5
template< typename T > void foo( T& x, int value )
{
    ++ T::static_member_variable ; // 'static_member_variable' is a dependant name
    ++value ; // 'value' is a non- dependant name
}


What a dependant name refers to could be something different for each different instantiation of the template. As a consequence, C++ templates are subject to "two-phase name lookup". When a template is initially parsed (before any instantiation takes place) the compiler looks up the non-dependent names. When a particular instantiation of the template takes place, the template parameters are known by then, and the compiler looks up dependent names.

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
struct A { void foo() {} } ;

template< typename T > struct B : public T
{
    void bar() {}
    void foobar()
    {
        //  'bar' is a non-dependant name.
        bar() ; // fine; found during phase one lookup

        // there is nothing here to tell the compiler that 'foo' is a dependant name.
        // its look up should be postponed to the second phase of the two-phase look up.
        // the compiler assumes that 'foo' is a non-dependant name
        foo() ; // *** error - 'foo' is not found  during phase one lookup

        // this is fine - the compiler knows that 'foo' is a dependant name
        // and postpones its lookup to phase two (where it will be bound if T is A)
        T::foo() ; // ok if T::foo is found during phase two lookup

        // this too is fine - the compiler knows that 'foo' is a dependant name
        // (because the type of the 'this' pointer B<T>* is dependant on T)
        // and postpones its lookup to phase two (where it will be bound if T is A)
        this->foo() ; // ok if T::foo is found during phase two lookup
        // note that in this case, if foo is virtual, it would be polymorphically dispathched.

    }
};

Topic archived. No new replies allowed.