9
votes

In the c++ standard [temp.point] it is written:

The instantiation context of an expression that depends on the template arguments is the set of declarations with external linkage declared prior to the point of instantiation of the template specialization in the same translation unit.

Then in [temp.dep.candidate]:

For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.

Does it means that the following code should fail:

namespace A{
    struct S{};
}

template<class T>
void g(T a){
    f(a); //f will be found by argument dependent lookup
}

namespace A{
    static void f(S); //but f doesn't have external linkage
}

void test(A::S i){
    g(i);
}
//point of instantiation of g
//A::f(S) doesn't have external linkage 
//=> so it's not in the instantiation context of template g ??

This code actually compiles, so what does this standard paragraph mean?

1
I was certain of my answer, until I read further to temp.dep.candidate-1.2. IIUC, that means you are correct. And A::f should not be found. What compilers did you try?StoryTeller - Unslander Monica
@StoryTeller I tried gcc and clang: compiler explorerOliv
@StoryTeller So I include this paragraph in the question. Still the answer you have deleted was clever, it may be was the intent of this paragraph.Oliv
Maybe it was. But that paragraph is pretty clear too. I think Clang and GCC are just falling back to the whole violation issue being ill-formed NDR. I'm not sure anymore :)StoryTeller - Unslander Monica
@StoryTeller What NDR requirement might apply here? The quoted paragraphs don't say NDR, and failure to find any candidate functions / a best viable function normally requires a diagnostic.aschepler

1 Answers

9
votes

This is a defect in the standard. Originally addressed in core issue 561, where the committee judged that

Notes from the April, 2006 meeting:

The consensus of the group was [..] that internal-linkage functions should be found by the lookup (although they may result in errors if selected by overload resolution).

Unfortunately the corresponding fix was insufficient, as elaborated in core issue 1258:

C++11 expanded the lookup rules for dependent function calls (17.7.4.2 [temp.dep.candidate] paragraph 1 bullet 2) to include functions with internal linkage; previously only functions with external linkage were considered. However, 17.7.4.1 [temp.point] paragraph 6 still says,

The instantiation context of an expression that depends on the template arguments is the set of declarations with external linkage declared prior to the point of instantiation of the template specialization in the same translation unit.

Presumably this wording was overlooked and should be harmonized with the new specification.

That is, the previous wording of your second quoted paragraph was

For the part of the lookup using associated namespaces (3.4.2), only function declarations with external linkage found in either the template definition context or the template instantiation context are found.

.. which was amended for C++11, but that change missed your first quote, making it rather pointless. The intent is that functions with internal linkage are not discriminated.