开发者

Why can't I call a templated method from a derived class instance in C++?

开发者 https://www.devze.com 2023-03-06 17:40 出处:网络
Please consider these types: struct X { static std::string fullyQualifiedName(); }; struct A { template <class T> void foo()

Please consider these types:

struct X
{
    static std::string fullyQualifiedName();
};


struct A
{
    template <class T> void foo()
    {
        return foo(T::fullyQualifiedName());
    }

protected:
    virtual void foo(const std::string& name) = 0;
};


struct B : public A
{开发者_StackOverflow中文版
protected:
    void foo(const std::string& name);
};

I have a pointer to an instance of B, I'm trying to invoke the templated version of foo like so:

b->foo< X >();

The compiler is complaining: 'X' : illegal use of this type as an expression.

On the other hand, this code's perfectly ok:

A* a = b;
a->foo< X >();

Hence my question.


The problem you are facing is called hiding. Basically the lookup rules in the language will start in the most derived type and work their way back up until it finds the appropriate symbol. In your case it will stop while looking at the B class as it finds void B::foo(const std::string& name). At that level, the only potential overload that it will consider is the one it is seeing.

To avoid hiding you can bring all the other overloads you can add a using declaration:

struct B : A{
   using A::foo;
   void foo( const std::string & name );
};

The difference is that lookup will work up the hierarchy until it finds the first overload, which is again at B level, but because of the using directive, it will also consider any overload available in A.

Alternatively, you can leave the symbol hidden and force dispatch to the exact class by qualifying the call (note that this has the side effect of disabling dynamic dispatch, which is not a problem here, but could be if the overload to use is virtual):

b->A::foo<X>();
0

精彩评论

暂无评论...
验证码 换一张
取 消