I came across the following situation in one of my projects, where a base class has a function template, which is hidden by a non-templated function in a derived class template. Further down the class hierarchy, the non-templated function is explicitly bringing the function into the scope via a using directive.
Here's a simplified example code:
class Base
{
public:
template<typename T> const T& get() const;
};
template<typename T> class Derived : public Base
{
private:
using Base::get;
public:
const T& get() const;
};
template<typename T> class MoreDerived : public Derived<T>
{
public:
using Derived<T>::get; // <-- this causes the problem
const T& call_get() {
return get();
}
};
template class MoreDerived<int>;
Godbolt: https://godbolt.org/z/5MQ0VL
The above code fails on GCC and Clang with errors like:
<source>:15:28: error: 'template<class T> const T& Base::get() const' is inaccessible within this context
15 | template<typename T> class MoreDerived : public Derived<T>
MSVC and ICC accept this code without complaints.
I'm wondering, why the compilers complain about Base::get<T>
while there is a public overload Derived<T>::get
available?
Removing the private using Base::get
from Derived<T>
leads to warnings about hiding functions from the base class. So this is unfortunately also not an ideal option.
Without the using Derived<T>::get
, calls to get
have to be qualified within MoreDerived
as it would not be a dependent name otherwise.
Any ideas, what I'm doing wrong here?
Derived<int> d; d.get<double>(); /* won't compile, but need: */ static_cast<Base>(d).get<double>();
– Simardget<U>
fail to compile forDerived<T>
is actually a feature of the original code. – Harnedconst
overload", or is it "why is theusing
declaration pulling in private declarations"? – Stodgyconst
overloads ofget
? So it's rather the latter. :-) – HarnedBase
publicly? Private inheritance should solve the issue. IfBase
needs to be inherited publicly, but the template getter shall be hidden anyway, you simply could make it protected – or you might move it to another base class that will be inherited privately. – Simard