ADL이 함수 템플릿을 찾지 못하는 이유는 무엇입니까?
C ++ 사양의 어떤 부분이 관련 네임 스페이스 집합에서 함수 템플릿을 찾지 못하도록 인수 종속 조회를 제한합니까? 즉, main
아래 의 마지막 호출 이 컴파일에 실패하는 이유는 무엇입니까?
namespace ns {
struct foo {};
template<int i> void frob(foo const&) {}
void non_template(foo const&) {}
}
int main() {
ns::foo f;
non_template(f); // This is fine.
frob<0>(f); // This is not.
}
이 부분에서 설명합니다.
C ++ 표준 03 14.8.1.6 :
[참고 : 간단한 함수 이름의 경우 함수 이름이 호출 범위 내에 표시되지 않는 경우에도 인수 종속 조회 (3.4.2)가 적용됩니다. 이는 호출이 여전히 함수 호출 (3.4.1)의 구문 형식을 가지고 있기 때문입니다. 그러나 명시 적 템플릿 인수가있는 함수 템플릿을 사용하는 경우 호출 지점에 해당 이름을 가진 함수 템플릿이 없으면 호출에 올바른 구문 형식이 없습니다. 그러한 이름이 표시되지 않으면 호출이 구문 상 제대로 구성되지 않았으며 인수 종속 조회가 적용되지 않습니다. 이러한 이름이 표시되면 인수 종속 조회가 적용되고 다른 네임 스페이스에서 추가 함수 템플릿을 찾을 수 있습니다.
namespace A {
struct B { };
template<int X> void f(B);
}
namespace C {
template<class T> void f(T t);
}
void g(A::B b) {
f<3>(b); //ill-formed: not a function call
A::f<3>(b); //well-formed
C::f<3>(b); //ill-formed; argument dependent lookup
// applies only to unqualified names
using C::f;
f<3>(b); //well-formed because C::f is visible; then
// A::f is found by argument dependent lookup
}
약간 받아 들여진 답변을 수정하고 싶습니다. OP 질문에서는 명확하지 않지만 표준 (Kornel에서 인용)에서 중요한 부분은 다음과 같습니다 (강조 내) :
그러나 명시 적 템플릿 인수가 있는 함수 템플릿을 사용하면 호출에 올바른 구문 형식이 없습니다.
따라서 금지 된 것은 ADL에 의존하고 명시적인 템플릿 인수를 사용하는 것입니다. 아쉽게도 형식이 아닌 템플릿 인수를 사용하려면 명시 적 인수를 사용해야합니다 (기본값이없는 경우).
다음은이를 보여주는 샘플 코드입니다. :
#include <string>
#include <utility>
namespace C {
struct B { };
template<class T> void f(T t){}
}
void g(C::B b) {
f(b); // OK
//f<C::B>(b); // ill-formed: not a function call, but only
// because explicit template argument were used
std::string s;
move(s); // OK
//move<std::string&>(s); // Error, again because
// explicit template argument were used
std::move<std::string&>(s); // Ok
}
int main()
{
C::B b;
g(b);
}
C ++ 20부터 adl은 명시 적 함수 템플릿에서도 잘 작동합니다. 제안은 다음과 같습니다. P0846R0 : 보이지 않는 ADL 및 기능 템플릿 :
Instead of requiring the user to use the template keyword, a revision to the lookup rules was proposed so that a name for which a normal lookup produces either no result or finds one or more functions and that is followed by a a "<" would treated as if a function template name had been found and would cause ADL to be performed.
Currently, only GCC 9 has implement this feature, so your example can compile.
Edit: No, this is not right. See @Kornel's answer.
I'm not entirely sure but having consulted Stroustrup's "The C++ programming language" I think that Appendix C section 13.8.4 might be the cause.
Since frob
is a template one could conceivably specialise it for i=0
at a point after you call it. This means that the implementation would be left with two possible ways of choosing which frob
to call as it appears it can choose it at the point of instantiation or at the end of processing the translation unit.
So, I think the problem is you could do
namespace ns {
struct foo {};
template<int i> void frob(foo const&) {}
}
int main() {
ns::foo f;
frob<0>(f);
return 0;
}
namespace ns {
template<> void frob< 0 >(foo const&) { /* Do something different*/ }
}
참고URL : https://stackoverflow.com/questions/2953684/why-doesnt-adl-find-function-templates
'Nice programing' 카테고리의 다른 글
생성자를 명시 적으로 삭제하는 이유는 무엇입니까? (0) | 2020.10.10 |
---|---|
git fast-forwarding이란 무엇입니까? (0) | 2020.10.10 |
Async await 키워드는 ContinueWith 람다와 동일합니까? (0) | 2020.10.10 |
.NET 용 명령 줄 인수 파서 찾기 (0) | 2020.10.10 |
libGDX에서 다른 종횡비를 처리하는 방법은 무엇입니까? (0) | 2020.10.10 |