I would suspect it's related to the infamous export
template feature of C++98. Think about it. Once you allow the possibility of template definitions appearing in separate translation units, but still not truly compilable until the template arguments are specified (i.e., the template is instantiated), you get into this twilight zone where the TU with the definition of the template and the TU with the instantiation have to obey linker-visibility rules (i.e., separation model) while sharing their contexts in terms of overload resolution. The solution to that problem is to allow only functions with external linkage in the dependent name lookups.
Here's an example. One of the lesser known "feature" of exported templates is that you could have, in the template's TU, some functions or classes with internal linkage (i.e., marked static
or in an un-named namespace). What if the TU with the instantiation has a internal-linkage function too, one that would be ambiguous with or possibly superceded by the one in the template's TU? That's a bit of a surreal problem, I know, it's the bizarro world of exported templates. The only way to avoid very surprising behavior is to rule out all internal-linkage functions from the lookups. Consider also that no-one had a clear idea of how to actually implement exported templates, and it would probably seem even more impossible to implement without this restriction.
And so, once exported templates are out, the restriction on dependent name lookups seems clearly useless and it was taken out without much debate. At least, that makes perfect sense to me, but, of course, it's speculation.
Here's a concrete example:
// in exptemp.h
export template <typename T> bool is_valid(T value);
// in exptemp.cpp
namespace {
bool is_space(char c) {
return (c == ' ') || (c == '');
};
};
template <typename T>
bool is_valid(T value) {
return is_space(value);
};
// in test.cpp
#include "exptemp.h"
namespace {
bool is_space(char c) {
return (c == ' ') || (c == '') || (c == '
');
};
};
int main() {
char c = '
';
return is_valid(c); // will this return 0 or 1 ?!?!?
};
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…