LcdDrm
LcdDrm

Reputation: 1009

Deleted function and ADL

I came across the following confusing example involving ADL and deleted functions:

First Example:

namespace A
{
    struct S{};

    void f(S){cout << "adl" << endl;}
}

namespace C
{
    //void f() = delete;

    //void f (double);

    void test()
    {
        A::S arg;
        f(arg);
    }
}


int main()
{
    C::test();

    return 0;
}

As expected, A::f is called through ADL. In the next example, there is a deleted function with the same name in C:

namespace A
{
    struct S{};

    void f(S){cout << "adl" << endl;}
}

namespace C
{
    void f() = delete;

    //void f (double);

    void testi()
    {
        A::S arg;
        f(arg);
    }
}


int main()
{
    C::testi();

    return 0;
}

Compiling fails with the error message error: use of deleted function 'void C::f()'. Apparently, the deleted functions stops the ADL version from getting into the overloading table. Now for the last example: In addition to the deleted function there is now another, not-deleted, function with the same name:

namespace A
{
    struct S{};

    void f(S){cout << "adl" << endl;}
}

namespace C
{
    void f() = delete;

    void f (double);

    void testi()
    {
        A::S arg;
        f(arg);
    }
}


int main()
{
    C::testi();

    return 0;
}

Running this executes the ADL version of f. So in conclusion:

My questions: Is this behaviour intentional? If so, which part of the standard specifies this?

Edit: I forgot to mention that I used onlinegdb for compilation, so gcc/g++ was used.

Upvotes: 1

Views: 131

Answers (1)

Definite compiler bug. To quote the C++ standard draft (n4659) [dcl.fct.def.delete]/2:

A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function is overloaded, it is referenced only if the function is selected by overload resolution. The implicit odr-use of a virtual function does not, by itself, constitute a reference.  — end note ]

Overload resolution cannot select that overload by ADL. So this function shouldn't be referenced. The second code sample is a well-formed C++ program (if the missing include directives are put back in).


You mentioned using g++ to compile, note that this issue is fixed in GCC 7.2.0

Upvotes: 1

Related Questions