0

I have something like this :

class Container1 {
  public:
    method1() { ... }
}
class Container2 {
  public:
    method1() { ... }
}

template<class C = Container1>
class X : public C {
  public:
    using C::method1();
    .....
    X(string& str) : C(str) {};
    X& other_method() { method1(); ...; }
}

My question is why I have to use "using C::method1()", to be able to access the method.. Most of answers I found is for the case where templated-class inhering templated-class. Normally they mention using "this->", but this does not seem to work in this case. Can I do something else shorter...

Also I'm suspecting the other error I'm getting is related to the same problem :

no match call for (X<Container1>) (<std::string&>)
sten
  • 7,028
  • 9
  • 41
  • 63
  • I think this is because you need to bring `method1` into the namespace of `X` there is no `method1` in X so the compiler looks locally and then for a global and does not find it. The `using` clause causes the compiler to look harder for `method1` – Adrian Cornish Sep 08 '12 at 02:46
  • 1
    An explanation of why you need either a `using` declaration or the `this->method1();` trick: http://www.parashift.com/c++-faq/nondependent-name-lookup-members.html – aschepler Sep 08 '12 at 02:50
  • @aschepler, thanks for the article. Although it sounds to me, like: "Sorry, we do not know how to write compilers....". The name lookup should simply work in this case. Dot. If not, go and fix your code. No excuses. – Kirill Kobelev Sep 08 '12 at 03:50

2 Answers2

1

First of all, in the definition of the ctor you should not use <C>. Most likely this confuses the compiler:

template<class C = Container1>
class X : public C 
{
    X(string& str) : C(str) { }
    X& other_method() { method1(); ...; }
}

Other point is that compiler may be not sure what should it call: base_class::method1() or template_param::method1(). In reality this is the same thing, but compiler may have a problem understanding this. I would not be surprised if different compilers will act differently here.

These are my 2 cents without running the tests.

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
1

Calling this->method1() probably fails since Container1::method1 and Container2::method1 are private. You can fix this by doing:

class Container1 {
public:
    void method1() { ... }
};

Then, going back to "why do I have to use using or this-> when calling methods defined in a template base class?", the answer is that method1 here is a dependent name, since it depends on the template argument C. Therefore you need to tell the compiler "Hey, you see this method1 call? Well, that symbol should be defined in the template class I'm inheriting.".

Since the compiler doesn't know what you're inheriting until you actually instantiate the class template, you must indicate that the member function should be defined by that template parameter. Otherwise, the compiler will see a call to a non-qualified function, and will generate an error, since no method named "method1" can be found in class X.

This thread contains some information on what dependent names are.

Another error in your code is your constructor:

X<C>(string& str) : ...

That code is ill-formed. The class X's constructor constructor should be defined this way:

X(string& str) : ....
Community
  • 1
  • 1
mfontanini
  • 21,410
  • 4
  • 65
  • 73