오버로드 된 함수에 대한 포인터를 어떻게 지정합니까?
과부하 된 함수를 std::for_each()
알고리즘 에 전달하고 싶습니다 . 예를 들어
class A {
void f(char c);
void f(int i);
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), f);
}
};
컴파일러가 f()
반복자 유형 으로 해결 될 것으로 기대합니다 . 분명히 (GCC 4.1.2) 그렇게하지 않습니다. 그렇다면 f()
원하는 것을 어떻게 지정할 수 있습니까?
함수 포인터 유형에 의해 암시 된 함수 서명에 따라 사용할 static_cast<>()
것을 지정하는 f
데 사용할 수 있습니다 .
// Uses the void f(char c); overload
std::for_each(s.begin(), s.end(), static_cast<void (*)(char)>(&f));
// Uses the void f(int i); overload
std::for_each(s.begin(), s.end(), static_cast<void (*)(int)>(&f));
또는 다음을 수행 할 수도 있습니다.
// The compiler will figure out which f to use according to
// the function pointer declaration.
void (*fpc)(char) = &f;
std::for_each(s.begin(), s.end(), fpc); // Uses the void f(char c); overload
void (*fpi)(int) = &f;
std::for_each(s.begin(), s.end(), fpi); // Uses the void f(int i); overload
경우 f
멤버 함수는, 당신은 사용이 필요 mem_fun
하거나 경우에, 사용 이 박사 Dobb의 기사에서 제시 한 솔루션을 .
구조에 람다! (참고 : C ++ 11 필요)
std::for_each(s.begin(), s.end(), [&](char a){ return f(a); });
또는 lambda 매개 변수에 decltype을 사용하십시오.
std::for_each(s.begin(), s.end(), [&](decltype(*s.begin()) a){ return f(a); });
다형성 람다 (C ++ 14) :
std::for_each(s.begin(), s.end(), [&](auto a){ return f(a); });
또는 과부하를 제거하여 명확하게 표현하십시오 (자유 기능에만 작동).
void f_c(char i)
{
return f(i);
}
void scan(const std::string& s)
{
std::for_each(s.begin(), s.end(), f_c);
}
왜 안돼?
컴파일러가
f()
반복자 유형 으로 해결 될 것으로 기대합니다 . 분명히 (gcc 4.1.2) 그렇게하지 않습니다.
그 경우라면 좋을 것입니다! 그러나 for_each
함수 템플릿은 다음과 같이 선언됩니다.
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
템플릿 공제 UnaryFunction
는 통화 시점에 유형을 선택해야합니다 . 그러나 f
특정 유형이 없습니다-과부하 된 기능이므로 f
각각 다른 유형을 가진 많은 것이 있습니다. for_each
템플릿 공제 프로세스가 f
원하는 것을 명시하여 템플릿 공제 프로세스를 지원하는 현재 방법이 없으므로 템플릿 공제가 단순히 실패합니다. 템플릿 공제에 성공하려면 콜 사이트에서 더 많은 작업을 수행해야합니다.
그것을 고치는 일반적인 해결책
몇 년 동안 여기에오고 나중에 C ++ 14. 오히려 사용을보다가 static_cast
(템플릿 공제하는 "고정"으로 성공할 수 있도록 것이다 f
우리가 사용하고자하지만, 수동으로 "수정"올바른 일에 오버로드 확인을 수행 할 필요), 우리는 우리를 위해 컴파일러 작품을 만들고 싶어. 우리는 f
일부 인수 를 요청하고 싶습니다 . 가능한 가장 일반적인 방법으로,
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
타이핑하기는 쉽지만 이런 종류의 문제는 성가신 일이 자주 발생하므로 매크로로 한 번 감싸는 것이 좋습니다.
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
그런 다음 사용하십시오.
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
이것은 컴파일러가 원하는 것을 정확하게 수행합니다-이름 f
자체 에 대한 과부하 해결을 수행하고 올바른 일을하십시오. 이것은 f
무료 기능인지 멤버 기능 인지에 관계없이 작동 합니다.
귀하의 질문에 대답하지는 않지만 내가 찾은 유일한 사람입니까
for ( int i = 0; i < s.size(); i++ ) {
f( s[i] );
}
both simpler and shorter than the for_each
alternative suggested by in silico in this case?
The problem here seems to be not overload resolution but in fact template parameter deduction. While the excellent answer from @In silico will solve an ambiguous overloading problem in general, it seems the best fix when dealing with std::for_each
(or similar) is to explicitly specify its template parameters:
// Simplified to use free functions instead of class members.
#include <algorithm>
#include <iostream>
#include <string>
void f( char c )
{
std::cout << c << std::endl;
}
void f( int i )
{
std::cout << i << std::endl;
}
void scan( std::string const& s )
{
// The problem:
// error C2914: 'std::for_each' : cannot deduce template argument as function argument is ambiguous
// std::for_each( s.begin(), s.end(), f );
// Excellent solution from @In silico (see other answer):
// Declare a pointer of the desired type; overload resolution occurs at time of assignment
void (*fpc)(char) = f;
std::for_each( s.begin(), s.end(), fpc );
void (*fpi)(int) = f;
std::for_each( s.begin(), s.end(), fpi );
// Explicit specification (first attempt):
// Specify template parameters to std::for_each
std::for_each< std::string::const_iterator, void(*)(char) >( s.begin(), s.end(), f );
std::for_each< std::string::const_iterator, void(*)(int) >( s.begin(), s.end(), f );
// Explicit specification (improved):
// Let the first template parameter be derived; specify only the function type
std::for_each< decltype( s.begin() ), void(*)(char) >( s.begin(), s.end(), f );
std::for_each< decltype( s.begin() ), void(*)(int) >( s.begin(), s.end(), f );
}
void main()
{
scan( "Test" );
}
If you don't mind using C++11, here's a clever helper that is similar to (but less ugly than) the static cast:
template<class... Args, class T, class R>
auto resolve(R (T::*m)(Args...)) -> decltype(m)
{ return m; }
template<class T, class R>
auto resolve(R (T::*m)(void)) -> decltype(m)
{ return m; }
(Works for member functions; should be obvious how to modify it to work for freestanding functions, and you should be able to provide both versions and the compiler will select the right one for you.)
With thanks to Miro Knejp for suggesting: see also https://groups.google.com/a/isocpp.org/d/msg/std-discussion/rLVGeGUXsK0/IGj9dKmSyx4J.
참고URL : https://stackoverflow.com/questions/2942426/how-do-i-specify-a-pointer-to-an-overloaded-function
'development' 카테고리의 다른 글
Swift 4에서 #selector ()를 사용하여 @objc 추론 폐기를 처리하는 방법은 무엇입니까? (0) | 2020.07.04 |
---|---|
.NET 앱의 최대 스레드 수? (0) | 2020.07.04 |
Bazel과 Gradle의 차이점은 무엇입니까? (0) | 2020.07.04 |
Java 웹 애플리케이션에서 애플리케이션 서버 외부에서 정적 데이터를 제공하는 가장 간단한 방법 (0) | 2020.07.04 |
차이점은 무엇입니까? (0) | 2020.07.04 |