For builtin types, argument dependent lookup (ADL) is not performed, therefore, an ignore
symbol must be "imported" into the current namespace.
You can, for example, do this; from most preferred to least preferred (i.e. to most intrusive and name polluting):
foobar::ignore (...)
using foobar::ignore; ignore(...);
using namespace foobar; ignore(...);
The error message comes up like this because in templates, you also enter the realm of dependent names and Two Phase Lookup. Names that depend on a template parameter, e.g.
template <typename T> void foo() {
T x;
x.frobnicate();
}
are looked up in phase 2, which is upon instantiation. Names that do not depend on template parameters, like
class Foo {};
template <typename T> void foo() {
Foo foo;
foo.frobnicate();
}
must be resolvable in the first phase.
This separation helps template authors to find bugs earlier and to find correct symbols, and it helps making templates more generic. For example, in C# generics, everything must be resolvable, which puts rather stringent limits on their flexibility (because everything that may be used by a generic must be defined). Oppositely, some old C++ compilers resolved in phase 2 only, i.e. at instantiation time, which had some subtle consequences for lookup and error finding.
The C++ 2-phase model combines the best of the eager-model (C#) and the lazy-model (some old C++ compilers).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…