g ++拒绝我的简单仿函数“预期类型,得到'xyz'”

时间:2009-05-05 14:04:37

标签: c++ templates g++ functor

我一直在玩C ++中的仿函数。特别是,我有一个对的向量,我想根据该对的第一个元素排序。我开始编写一个完全专业的函子(例如“bool MyLessThan(MyPair& lhs,MyPair& rhs)”)。然后,仅仅因为这种东西很有趣,我想尝试编写一个通用的“将F应用于这对的第一个元素”仿函数。我写了下面的内容,但是g ++并不喜欢它。我明白了:

错误:模板参数列表中参数2的类型/值不匹配'template struct Pair1stFunc2' 错误:期望一个类型,得到'更少'

#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。

5 个答案:

答案 0 :(得分:6)

为了扩展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>());
}

请注意它有效,但可能与您的想法不同。

答案 1 :(得分:3)

请注意,std::less本身就是一个模板,当您使用foo()函数的sort调用模板模板参数时,您不会指定模板模板参数!这里less是一个不完整的类型,因此存在问题。

答案 2 :(得分:2)

您需要使用您正在使用的比较类型来专门化std :: less。

Pair1stFunc2<MyPair, std::less<int> >()

会做到这一点。在您自己的operator()中,您还需要实例化比较类型的对象,因为您不能直接调用该类。例如。变化

return F(lhs.first, rhs.first);

F func;
return func(lhs.first, rhs.first);

另一个答案表明,你也可以将专业化转移到仿函数中。

答案 3 :(得分:2)

与unwesen类似。但您不需要使用模板模板。

#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
}

答案 4 :(得分:1)

最简单的解决方案是陈述你想要的参数,一个具有合适签名的函数:

template<typename P, bool (*F)(P,P)> struct Pair1stFunc2 { ... }

在这种情况下,将函数模板作为第二个参数传递将导致对其执行重载解析,并将P,P作为参数类型。这是有效的,因为您将重载决议移出struct Pair1stFunc2::operator()

您还希望传入仿函数的可能性,但那些确实需要作为模板类型参数传递,然后在operator()中创建:

typename F::result_type operator()(const P &lhs, const P &rhs) const
{ return F()(lhs.first, rhs.first); }

这里,F是仿函数类型,F()是该仿函数的一个实例。

前面已经介绍了第三种情况,即仿函数模板。 std :: less就是这样一个模板。在这种情况下,您需要一个模板模板参数。