1

Let's have following code:

//template <typename ... A>
//void foo(char a, A ... args);

template <typename T> void P(T x) { std::cout << x << ' '; }

void foo(char a) { P(3); P(a); }

template <typename ... A>
void foo(int a, A ... args)
{
    foo(args...);
    P(a);
}

template <typename ... A>
void foo(char a, A ... args)
{
    P(a);
    foo(args...);
}

int main()
{
    foo('1', '2', 48, '4', '5');
}

It behaves differently on MSVC2015 and ideone's GCC

When args... equals 48, '4', '5', foo is called. Compilers differs on which foo is called. MSVC takes into account overloads defined bellow actual call (without declaration before) whereas GCC works only with already declared overloads. If I uncomment the declaration, both MSVC and GCC print 1 2 4 3 5 48. If declaration is commented out, MSVC prints the same, but GCC prints 1 2 3 5 52 48 (52 is ascii for 4)

Which compiler is right according to the standard?

I have n4296 draft available, but I've failed to find an answer there, the document is kind of unreadable for me...

relaxxx
  • 7,566
  • 8
  • 37
  • 64

1 Answers1

1

MSVC fails to implement two phase name lookup for templates as prescribed by the standard. This compiler incorrectly defers all name resolution to the point of template instantiation.

Other compilers correctly resolve non-dependent names at the point of template definition. That's the reason for the difference you observe. At the point of definition, the second foo template is invisible so a conforming compiler cannot use it. But at the point of instantiation, it is visible and MSVC happily finds it.

Community
  • 1
  • 1
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243