3

Why do I have to reintroduce the name of a function having some of its overloads deleted ?

#include <string>

struct A
{
    void f(int) {}
    void f(double) {}
    void f(const std::string&) {}
};

struct B : public A
{
    using A::f; // needed to compile : why ?
    void f(int)=delete;
    void f(double)=delete;
};

int main()
{
    B b;
    b.f(std::string("toto"));
}
0

3 Answers 3

3

A single declaration of f in the B class hides all declarations of f from the base A class.

And even marking the functions as deleted is considered a declaration.

Sign up to request clarification or add additional context in comments.

Comments

2

These records within the structure B

void f(int)=delete;
void f(double)=delete;

are declarations that hide the declarations with the same name f in the base structure A.

So the using declaration in B

using A::f; // needed to compile : why ?

makes all functions with the name f declared in A visible in the structure B.

Consider the following demonstrative program where in one case there is no using declaration and in the second case there is a using declarations.

#include <iostream>

int main() 
{
{   
    struct A
    {
        void f( char ) const
        {
        std::cout << "A::f( char ) const\n";
        }
    };

    struct B : A
    {
        void f( int ) const
        {
            std::cout << "B::f( int ) const\n";
        }
    };


    B b;
    
    b.f( 'A' );
}

std::cout << '\n';

{   
    struct A
    {
        void f( char ) const
        {
        std::cout << "A::f( char ) const\n";
        }
    };

    struct B : A
    {
        using A::f;
        void f( int ) const
        {
            std::cout << "B::f( int ) const\n";
        }
    };


    B b;
    
    b.f( 'A' );
}

    return 0;
}

The program output is

B::f( int ) const

A::f( char ) const

Comments

1

It's legalistic, but at least it's consistent.

I think you're thinking that when a function is overridden in a derived class, the mechanism there is that the function from the base class, or at least its identifier, is conceptually imported into the derived class and then overridden. But really, what's happening is that code which calls b.f never even sees A::f, because the lookup succeeds before it gets there. All that happens before overload resolution takes place.

So if you want to have access to the various overloads from A alongside those of B (including the deleted ones), you need to import them into B, so the compiler doesn't give up before seeing them.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.