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> ();
    ^
Dr. Gut
  • 2,053
  • 7
  • 26
  • 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 work – Alan Birtles Aug 14 '19 at 21:08
  • Neither of the three compilers enforce this. If you remove `constexpr` in the commented line, all thee compile it successfully. – Dr. Gut Aug 16 '19 at 17:48
  • An extremely bizarre observation! – curiousguy Oct 29 '19 at 19:41

1 Answers1

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 :/

Dr. Gut
  • 2,053
  • 7
  • 26
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • 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. – Dr. Gut Aug 16 '19 at 17:52