4

On cppreference.com, the following code is provided as example explaining dependent name resolution:

#include <iostream>
void g(double) { std::cout << "g(double)\n"; }

template<class T>
struct S {
    void f() const {
        g(1); // "g" is a non-dependent name, bound now
    }
};

void g(int) { std::cout << "g(int)\n"; }

int main()
{
    g(1); // calls g(int)

    S<int> s;
    s.f(); // calls g(double)
}

The current version of Visual C++ (19.0.23918.0) produces the following output:

g(int)
g(int)

Is this allowed by the standard, or is it a bug in MSVC?

kinokijuf
  • 968
  • 1
  • 11
  • 33
  • `clang++` gives output `g(int)` & `g(double)`. See live demo [here](http://coliru.stacked-crooked.com/a/11abfefb3f2b642b) – Destructor Jun 08 '16 at 13:09
  • [temp.nondep](http://eel.is/c++draft/temp.res#temp.nondep). Not that difficult to google. – uh oh somebody needs a pupper Jun 08 '16 at 13:09
  • 1
    It's mid-2016. Everybody who has knowledge enough to understand dependent vs non-dependent name resolution should be well aware of MSVC idiosincriasies regarding two-step template instantiation. – SergeyA Jun 08 '16 at 13:15

1 Answers1

3

"Dependent name resolution" is misleading here. g is a non-dependent name so the rules that apply are temp.nondep not temp.dep.res:

Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used. [ Example:

void g(double);
void h();

template<class T> class Z {
public:
  void f() {
    g(1);           // calls g(double)
    h++;            // ill-formed: cannot increment function;
                    // this could be diagnosed either here or
                    // at the point of instantiation
  }
};

void g(int);        // not in scope at the point of the template
                    // definition, not considered for the call g(1)

end example ]

This is virtually identical to the example on cppreference. So yes, it is a bug in MSVC.

  • @M.M. has a very interesting point of view, claiming that it falls under 'program is ill-formed, no diagnostic is required' and thus not an MSVC bug. – SergeyA Jun 08 '16 at 13:16
  • @SergeyA I don't see a link? – uh oh somebody needs a pupper Jun 08 '16 at 13:22
  • @SergeyA "No diagnostic required" is not mutually exclusive with "bug". Here, we see an example contradicting MSVC's behavior, so it is a bug. The standard doesn't say "ill-formed" so a diagnostic isn't required here regardless. – uh oh somebody needs a pupper Jun 08 '16 at 13:22
  • I do not know how to link a particular comment, so here is the link to the question: http://stackoverflow.com/questions/37599877/why-an-incomplete-type-is-detected-in-clang-inside-a-template-method/37599922?noredirect=1#comment62684779_37599922 and there open comments under my answer. And I was wrong, it wasn't M.M., but @T.C. – SergeyA Jun 08 '16 at 13:27
  • @SergeyA It doesn't apply here though. See [CWG 1850](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1850) for insight on what it's actually supposed to mean. – uh oh somebody needs a pupper Jun 08 '16 at 13:41
  • I am afraid, it's a bit lost on me. Would you mind providing simplified explanation? (if you have time and energy for this, of course). – SergeyA Jun 08 '16 at 13:45
  • @SergeyA The striked out text illustrates that it applies mainly to "incomplete types" (which was the issue in the question you linked). But none of the expanded bulleted points in the new text apply to OP's situation here. – uh oh somebody needs a pupper Jun 08 '16 at 13:50
  • Got it! Thanks a lot. – SergeyA Jun 08 '16 at 13:54