ADL does not work in constexpr functions (clang only)
Asked Answered
I

1

7

The following code compiles with MSVC and gcc, but not with clang. Why is that so?

It seems like if ADL would not work if CallFoo () is constexpr. See the comment.

template <class T>
constexpr void CallFoo  ()          // Remove constexpr to fix clang compilation error.
{
    Foo (T ());
}


class Apple {};


int main ()
{
    CallFoo<Apple> ();
}


constexpr void Foo (Apple)
{
}

Clang error message (see on godbolt.org):

<source>:4:5: error: use of undeclared identifier 'Foo'
    Foo (T ());
    ^
<source>:13:5: note: in instantiation of function template specialization 'CallFoo<Apple>' requested here
    CallFoo<Apple> ();
    ^
Intuitional answered 14/8, 2019 at 21:1 Comment(3)
Clang enforces the rule that functions must be declared before they are instantiated by a template, move your function declaration higher up and it'll probably workZacheryzack
Neither of the three compilers enforce this. If you remove constexpr in the commented line, all thee compile it successfully.Intuitional
An extremely bizarre observation!Fleabite
B
1

Declaration should be visible at the point of instantiation, so clang has right to reject your code. Reordering functions fixes compilation:

constexpr void Foo (Apple)
{
}

int main ()
{
    CallFoo<Apple> ();
}

Demo

Fact is that end of file is a point of instantiation too, and gcc/MSVC should only consider this one :/

Balladmonger answered 15/8, 2019 at 7:4 Comment(1)
Neither of the three compilers enforce that declarations should be visible at the point of instantiation. If you remove constexpr in the commented line, all thee compile it successfully.Intuitional

© 2022 - 2024 — McMap. All rights reserved.