G ++는 "예상 유형, 'xyz'를 통해 내 간단한 기능을 거부합니다.
문제
나는 C ++의 Functors와 함께 놀았습니다. 특히, 나는 쌍의 첫 번째 요소로 정렬하고 싶은 쌍의 쌍을 가지고 있습니다. 나는 완전히 전문화 된 기능을 작성하기 시작했습니다 (즉, "bool myless than (mypair & lhs, mypair & rhs)"과 같은 것). 그런 다음 이런 종류의 것들이 흥미로워서 일반적인 "이 쌍의 첫 번째 요소에 적용 f"functor를 작성하려고했습니다. 아래를 썼지 만 G ++는 그것을 좋아하지 않습니다. 나는 얻다:
오류 : 'Template struct pair1stfunc2'에 대한 템플릿 매개 변수 목록에서 인수 2에서 유형/값 불일치 '오류 : 예상 유형,'Less '가 있습니다.
#include <algorithm>
#include <functional>
#include <utility>
#include <vector>
template <class P, class F>
struct Pair1stFunc2
{
typename F::result_type operator()(P &lhs, P &rhs) const
{ return F(lhs.first, rhs.first); }
typename F::result_type operator()(const P &lhs, const P &rhs) const
{ return F(lhs.first, rhs.first); }
};
typedef std::pair<int,int> MyPair;
typedef std::vector<MyPair> MyPairList;
MyPairList pairs;
void foo(void)
{
std::sort(pairs.begin(),
pairs.end(),
Pair1stFunc2<MyPair, std::less>());
}
누구든지 내가 여기서 잘못하고있는 일에 대해 빛을 발할 수 있습니까? 나는 이것이 약간 인공적인 예라는 것을 알고 있지만, STL-FU를 개선하기 위해서만 무슨 일이 일어나고 있는지 알고 싶습니다.
해결책
사용중인 비교 유형을 사용하여 std ::를 전문화해야합니다.
Pair1stFunc2<MyPair, std::less<int> >()
트릭을 할 것입니다. 자신의 Operator () 내에서 클래스를 직접 호출 할 수 없으므로 비교 유형의 객체를 인스턴스화해야합니다. 예 : 변화
return F(lhs.first, rhs.first);
에게
F func;
return func(lhs.first, rhs.first);
또 다른 대답에서 알 수 있듯이 전문화를 펀치로 옮길 수도 있습니다.
다른 팁
Dirkgently의 답변을 확장하려면 다음은 의도 한대로 작동 할 수있는 예가 있습니다.
template <typename T, template <typename> class F>
struct Pair1stFunc2
{
template <typename P>
typename F<T>::result_type operator()(P &lhs, P &rhs) const
{ F<T> f; return f(lhs.first, rhs.first); }
template <typename P>
typename F<T>::result_type operator()(const P &lhs, const P &rhs) const
{ F<T> f; return f(lhs.first, rhs.first); }
};
void foo(void)
{
std::sort(pairs.begin(),
pairs.end(),
Pair1stFunc2<int, std::less>());
}
그것이 작동하지만 정확히 당신이 생각한 것이 아닐 수도 있습니다.
주목하십시오 std::less
그 자체가 템플릿이며 템플릿 템플릿 매개 변수를 호출 할 때 템플릿 템플릿 매개 변수를 지정하지 않습니다. foo()
기능 sort
! 여기 less
불완전한 유형이므로 문제입니다.
Unkesen과 유사합니다. 그러나 템플릿 템플릿을 사용할 필요는 없습니다.
#include <algorithm>
#include <functional>
#include <memory>
#include <vector>
typedef std::pair<int,int> MyPair;
typedef std::vector<MyPair> MyPairList;
MyPairList pairs;
// Same as original.
template <typename T,typename F>
struct Pair1stFunc2
{
template <typename P>
typename F::result_type operator()(P &lhs, P &rhs) const
{ F f; // Just need to create an anstance of the functor to use.
return f(lhs.first, rhs.first); }
template <typename P>
typename F::result_type operator()(const P &lhs, const P &rhs) const
{ F f; // Just need to create an anstance of the functor to use.
return f(lhs.first, rhs.first); }
};
void foo(void)
{
std::sort(pairs.begin(),
pairs.end(),
Pair1stFunc2<int, std::less<int> >()); // initialize the version of less
}
가장 간단한 해결책은 당신이 원하는 것을 인수로 말하고 적절한 서명을 가진 기능을 말하는 것입니다.
template<typename P, bool (*F)(P,P)> struct Pair1stFunc2 { ... }
이 경우, 두 번째 인수로 함수 템플릿을 전달하면 인수 유형으로 p, p로 과부하 해결이 수행됩니다. 과부하 해상도를 struct Pair1stFunc2::operator()
당신은 또한 a를 통과 할 가능성을 원합니다 untctor, 그러나 그 사람들은 템플릿 유형 인수로 전달 된 다음 OPERATOR () 내에서 만들어 져야합니다.
typename F::result_type operator()(const P &lhs, const P &rhs) const
{ return F()(lhs.first, rhs.first); }
여기서 F는 functor 유형이고 f () 해당 functor의 인스턴스입니다.
세 번째 사례는 이미 앞서 다루어졌습니다. Functor 템플릿. STD :: 덜 템플릿입니다. 이 경우 템플릿 템플릿 인수가 필요합니다.