Re: [问题] overload 加上 namespace 之后会 fail

楼主: jackace (inevitable......)   2014-07-31 19:38:32
以下是个人的解释不知道对不对
spec: N3485
14.6/p9
When looking for the declaration of a name used in a template definition,
...
The lookup of names dependent on the template parameters is
postponed until the actual template argument is known
14.6.2/p1
In an expression of the form:
postfix-expression ( expression-list)
where the postfix-expression is an unqualified-id, the unqualified-id denotes
a dependent name if
— any of the expressions in the expression-list is a pack expansion ,
— any of the expressions in the expression-list is a type-dependent expression,
or
— if the unqualified-id is a template-id in which any of the template
arguments depends on a template parameter.
If an operand of an operator is a type-dependent expression, the operator
also denotes a dependent name. Such names are unbound and are looked up at
the point of the template instantiation (14.6.4.1) in both
the context of the template definition and
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
the context of the point of instantiation.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14.6.4.1/p1
For a function template specialization,
...
if the specialization is implicitly instantiated because it is referenced
from within another template specialization and the context from which it is
referenced depends on a template parameter, the point of instantiation of the
specialization is the point of instantiation of the enclosing specialization.
Otherwise, the point of instantiation for such a specialization immediately
follows the namespace scope declaration or definition that refers to the
specialization.
首先 base case定义于general case之后
因此, 不论有没有加namespace,
想在the context of the template definition中找到base case是不可能的
同时 _set_nth_element的general case永远找的到自己
所以问题在于 为什么没加namespace的时候 就能在
the context of the point of instantiation中找的到base case
以下将point of instantiation简写为POI
没有namespace的时候 apply 14.6.4.1得到
main ->
set_nth_element<7> -> POI在set_nth_element之后
_set_nth_element<0> -> POI在set_nth_element之后
_set_nth_element<1> -> ...
_set_nth_element<7> POI在set_nth_element之后
既然POI在set_nth_element之后 就能找到_set_nth_element的base case
加了namespace之后 虽然POI在set_nth_element之后
但_set_nth_element的general还是无法找到处于detail中的base case
如果在set_nth_element的definition之前加上
using detail::_set_nth_element;
就可以正常编译了
以上看起来好像很顺 但其实有问题
14.6.4.2 Candidate functions [temp.dep.candidate]
For a function call where the postfix-expression is a dependent name, the
candidate functions are found using the usual lookup rules (3.4.1, 3.4.2)
except that:
— For the part of the lookup using unqualified name lookup (3.4.1), only
function declarations from the template definition context are found.
— For the part of the lookup using associated namespaces (3.4.2), only
function declarations found in either the template definition context
or the template instantiation context are found
事实上 要在instantiation context中进行lookup 必须透过Argument Dependent Lookup
那么
_set_nth_element<CUR_IDX+1>(
p, f,
std::integral_constant<int, LeftDistance::value-1>()
);
的argument中, p是fundamental type没有associated namespace
std::integral_constant的associated namespace就是std所以也连不到global namespace
f呢?
f是个lambda expression产生的closure object
closure object依照spec来说是个local class 本不应该有associated namespace
所以照理来说原本的程式就算不加namespace detail也不应该能编译
(因为general case还是应该找不到base case)
应该一番google 看起来似乎是g++的bug:
https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/6Mp0OUawJ8M
"It appears that g++ includes the enclosing namespaces as associated
namespaces for local classes, contrary to the current rules in the standard."
所以我把你原本的程式(没有detail namespace)用clang 3.4.1去编:
http://gcc.godbolt.org/
一样会有类似的错误
note: in instantiation of function template specialization
'_set_nth_element<254, int *, <lambda at
/tmp/gcc-explorer-compiler114631-16727-xtob8u/example.cpp:65:31>,
std::integral_constant<int, -247> >' requested here
请注意上面的254跟-247 一样代表展开时没找到base case
以上推导不知道对不对
作者: johnjohnlin (嗯?)   2014-08-02 11:45:00
感谢大大热心专业的回复~~
作者: saladim (杀拉顶)   2014-08-13 07:09:00
太专业了 @_@ 头有点痛

Links booklink

Contact Us: admin [ a t ] ucptt.com