The following C++ code should not compile: template<class T> int t(T i) { return f (i); // error: f not visible here } int f (int i) { return i; } int main() { return t(1); } The C++ standard clause 14.6.3 states that names should be looked up from the point they are used. I.e. functions defined after that point are not visible. This is true for regular functions, but GCC does not get this right for template functions.
(In reply to comment #0) > The C++ standard clause 14.6.3 states that names should be looked up from the > point they are used. I.e. functions defined after that point are not visible. > This is true for regular functions, but GCC does not get this right for > template functions. No you missed something but I don't have the standard in front of me. 14.6.3 is talking about something different. Anyways this is unqualified function call that is dependent on a template arguments. I think 14.6.3 is really talking about what PR 2922 is about and not this one.
Actually wait, what is happening here is ADL is happening for fundemantal types which is a question of a Defect report, I forgot which one now.
Actually you missed 14.6.4.2. This really has nothing to do with 14.6.3.
Also "f (i)" is a dependent expression because of 14.6.2/1 as i is (obviously) dependent so 14.6.3 does not apply.
So GCC does not implement 14.6.4.2/1, part 1: - For the part of look using unqualified name lookup (3.4.1), only function declareations with external linkage from the template context are found. And since ADL on fundalment types not exist, that is the only part that happens so this is invalid code based on that and nothing else. Next time becareful when trying to figuring out why something is invalid code because it is easy to get it wrong and then have a someone else having to look at the standard to prove you wrong. In fact the following is valid code because of ADL (since template instantiation conext is also included for ADL): template<class T> int t(T i) { return f (i); // error: f not visible here } struct a{}; int f (a i) { return 0; } int main() { a b; return t(b); }
This is DR 225 really. http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#225 Which means there is a question if this is really invalid code after all.
*** Bug 42281 has been marked as a duplicate of this bug. ***
*** Bug 34886 has been marked as a duplicate of this bug. ***
*** Bug 31816 has been marked as a duplicate of this bug. ***
*** Bug 43261 has been marked as a duplicate of this bug. ***
*** Bug 43506 has been marked as a duplicate of this bug. ***
*** Bug 45132 has been marked as a duplicate of this bug. ***
*** Bug 46075 has been marked as a duplicate of this bug. ***
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#225 is now NAD (I think that should un-suspend several PRs)
*** Bug 36883 has been marked as a duplicate of this bug. ***
Author: jason Date: Fri May 20 18:01:22 2011 New Revision: 173965 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=173965 Log: PR c++/24163 PR c++/29131 gcc/cp/ * pt.c (tsubst_copy_and_build) [CALL_EXPR]: Avoid repeating unqualified lookup. * semantics.c (perform_koenig_lookup): Add complain parm. * cp-tree.h: Adjust. * parser.c (cp_parser_postfix_expression): Adjust. (cp_parser_perform_range_for_lookup): Adjust. libstdc++-v3/ * include/ext/pb_ds/assoc_container.hpp: Explicitly qualify calls to functions from dependent bases. * include/ext/pb_ds/detail/rb_tree_map_/erase_fn_imps.hpp: Likewise. * include/ext/pb_ds/detail/rb_tree_map_/ split_join_fn_imps.hpp: Likewise. * include/ext/pb_ds/detail/splay_tree_/erase_fn_imps.hpp: Likewise. * include/ext/pb_ds/detail/splay_tree_/insert_fn_imps.hpp: Likewise. * include/ext/pb_ds/detail/splay_tree_/splay_fn_imps.hpp: Likewise. * include/ext/pb_ds/detail/splay_tree_/ split_join_fn_imps.hpp: Likewise. * include/ext/pb_ds/detail/tree_policy/ order_statistics_imp.hpp: Likewise. * include/ext/pb_ds/detail/trie_policy/ prefix_search_node_update_imp.hpp: Likewise. * include/ext/rc_string_base.h: Likewise. * include/ext/rope: Likewise. * include/ext/ropeimpl.h: Likewise. * testsuite/util/exception/safety.h: Likewise. * testsuite/util/native_type/native_priority_queue.hpp: Likewise. * testsuite/util/testsuite_io.h: Likewise. * include/std/functional: Declare mem_fn earlier. * include/tr1/functional: Likewise. * include/tr1/exp_integral.tcc: Declare __expint_E1 earlier. Added: trunk/gcc/testsuite/g++.dg/template/koenig9.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.h trunk/gcc/cp/parser.c trunk/gcc/cp/pt.c trunk/gcc/cp/semantics.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/opt/pr47615.C trunk/gcc/testsuite/g++.dg/overload/defarg1.C trunk/gcc/testsuite/g++.dg/tc1/dr213.C trunk/gcc/testsuite/g++.dg/torture/pr34850.C trunk/gcc/testsuite/g++.dg/torture/pr39362.C trunk/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C trunk/gcc/testsuite/g++.old-deja/g++.pt/memtemp47.C trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/ext/pb_ds/assoc_container.hpp trunk/libstdc++-v3/include/ext/pb_ds/detail/rb_tree_map_/erase_fn_imps.hpp trunk/libstdc++-v3/include/ext/pb_ds/detail/rb_tree_map_/split_join_fn_imps.hpp trunk/libstdc++-v3/include/ext/pb_ds/detail/splay_tree_/erase_fn_imps.hpp trunk/libstdc++-v3/include/ext/pb_ds/detail/splay_tree_/insert_fn_imps.hpp trunk/libstdc++-v3/include/ext/pb_ds/detail/splay_tree_/splay_fn_imps.hpp trunk/libstdc++-v3/include/ext/pb_ds/detail/splay_tree_/split_join_fn_imps.hpp trunk/libstdc++-v3/include/ext/pb_ds/detail/tree_policy/order_statistics_imp.hpp trunk/libstdc++-v3/include/ext/pb_ds/detail/trie_policy/prefix_search_node_update_imp.hpp trunk/libstdc++-v3/include/ext/rc_string_base.h trunk/libstdc++-v3/include/ext/rope trunk/libstdc++-v3/include/ext/ropeimpl.h trunk/libstdc++-v3/include/std/functional trunk/libstdc++-v3/include/tr1/exp_integral.tcc trunk/libstdc++-v3/include/tr1/functional trunk/libstdc++-v3/testsuite/util/exception/safety.h trunk/libstdc++-v3/testsuite/util/native_type/native_priority_queue.hpp trunk/libstdc++-v3/testsuite/util/testsuite_io.h
Fixed for 4.7.
*** Bug 41995 has been marked as a duplicate of this bug. ***
I am having a problem using code similar to the one in comment #5, but using glm::vec3, from the glm library (http://glm.g-truc.net/), as the type used to instanciate the template. Then I get an error message that "‘f’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation" glm::vec3 does not seem like a fundamental type. #include "glm/glm.hpp" template<class T> int t(T i) { return f (i); } int f (glm::vec3 i) { return 0; } int main() { glm::vec3 b; return t(b); }
(In reply to comment #20) > glm::vec3 does not seem like a fundamental type. It isn't, but its associated namespace is glm, and your f isn't in glm.
I am sorry if my knowledge on this issue is limited, but if I put t() and f() in namespace glm (re. the code in comment #20), should this compile? (That is what you comment #19 implies). Actually it does not.
(In reply to comment #22) > I am sorry if my knowledge on this issue is limited, but if I put t() and f() > in namespace glm (re. the code in comment #20), should this compile? (That is > what you comment #19 implies). Actually it does not. That's surprising, but I would need a self-contained testcase to comment further.
(In reply to comment #22) > I am sorry if my knowledge on this issue is limited, but if I put t() and f() > in namespace glm (re. the code in comment #20), should this compile? (That is > what you comment #19 implies). Actually it does not. So you are talking about this? Notice how vec3 isn't actually in glm. Interactions between namespaces and name lookup can be difficult. namespace glm { namespace detail { struct vec3{}; } using detail::vec3; } template<class T> int t(T i) { return f (i); } namespace glm { int f (glm::vec3 i) { return 0; } } int main() { glm::vec3 b; return t(b); }
The situation in the actual glm is more like the following. We also put t() and f() in namespace glm as well, se we get the following code, which produces the error: namespace glm { namespace detail { struct dvec3{}; } typedef detail::dvec3 vec3; } namespace glm { template<class T> int t(T i) { return f (i); } int f (glm::vec3 i) { return 0; } } int main() { glm::vec3 b; return glm::t(b); }