g++;用“拒绝我的简单函子”;应为一个类型,得到';xyz'&引用; 我一直在玩C++中的函子。特别是,我有一个向量对,我想按对的第一个元素排序。我开始写一个完全专业化的函子(比如“bool MyLessThan(MyPair&lhs,MyPair&rhs)”)。然后,就因为这类东西很有趣,我想尝试编写一个通用的“将F应用于这对元素的第一个元素”函子。我写了下面的代码,但是g++不喜欢它。我得到:

g++;用“拒绝我的简单函子”;应为一个类型,得到';xyz'&引用; 我一直在玩C++中的函子。特别是,我有一个向量对,我想按对的第一个元素排序。我开始写一个完全专业化的函子(比如“bool MyLessThan(MyPair&lhs,MyPair&rhs)”)。然后,就因为这类东西很有趣,我想尝试编写一个通用的“将F应用于这对元素的第一个元素”函子。我写了下面的代码,但是g++不喜欢它。我得到:,c++,templates,g++,functor,C++,Templates,G++,Functor,错误:“模板结构Pair1stFunc2”的模板参数列表中参数2的类型/值不匹配 错误:应为类型,但得到“less” #include <algorithm> #include <functional> #include <utility> #include <vector> template <class P, class F> struct Pair1stFunc2 { typename F::result_type op

错误:“模板结构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>());
}
#包括
#包括
#包括
#包括
模板
结构Pair1stFunc2
{
typename F::结果类型运算符()(P&lhs,P&rhs)常量
{返回F(lhs.first,rhs.first);}
typename F::result_type operator()(常量P&lhs、常量P&rhs)常量
{返回F(lhs.first,rhs.first);}
};
typedef std::pair MyPair;
typedef std::向量MyPairList;
MyPairList对;
无效foo(无效)
{
std::sort(pairs.begin(),
pairs.end(),
Pair1stFunc2());
}

有人能解释一下我做错了什么吗?我知道这只是一个稍微做作的例子,但我想知道发生了什么,如果只是为了改进我的STL fu。

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

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

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


您还可以将专门化移到函子中,正如另一个答案所建议的那样。

要扩展Dirkgente的答案,下面是一个可能按照您的意愿工作的示例:

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>());
}
模板
结构Pair1stFunc2
{
模板
typename F::结果类型运算符()(P&lhs,P&rhs)常量
{F;返回F(lhs.first,rhs.first);}
模板
typename F::result_type operator()(常量P&lhs、常量P&rhs)常量
{F;返回F(lhs.first,rhs.first);}
};
无效foo(无效)
{
std::sort(pairs.begin(),
pairs.end(),
Pair1stFunc2());
}

请注意,它是有效的,但可能与您的想法不完全一致。

最简单的解决方案是将您想要的作为参数,一个具有适当签名的函数:

template<typename P, bool (*F)(P,P)> struct Pair1stFunc2 { ... }
这里,F是函子类型,F()是该函子的实例


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

类似于Unwsen。但是您不需要使用模板

#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
}
#包括
#包括
#包括
#包括
typedef std::pair MyPair;
typedef std::向量MyPairList;
MyPairList对;
//和原件一样。
模板
结构Pair1stFunc2
{
模板
typename F::结果类型运算符()(P&lhs,P&rhs)常量
{F;//只需要创建一个要使用的函子实例。
返回f(左首,右首);}
模板
typename F::result_type operator()(常量P&lhs、常量P&rhs)常量
{F;//只需要创建一个要使用的函子实例。
返回f(左首,右首);}
};
无效foo(无效)
{
std::sort(pairs.begin(),
pairs.end(),
Pair1stFunc2());//初始化less的版本
}

不过,他实际上并没有在MyPair中使用std::less,而是使用std::less。一旦解决了这个问题,就会有另一个问题,因为F是一种类型。您正在使用lhs.first和rhs.first构造一个新的F。您会发现std::less没有两个参数的构造函数。您需要有一个类型为F的值。下面是一些改进boost::bind fu:sort(p.begin()、p.end()、bind(less()、bind(&MyPair::first,_1)、bind(&MyPair::first,_2));)基本正确,但我认为std::less的实例是函子。可以使用语法F(参数列表)调用函子。你不能这样调用std::less。(删除我的注释,因为它在编辑之前引用了答案)你是否建议对Pair1stFunc2::operator()(lhs,rhs)使用两个单独的语法,一个用于函数指针,另一个用于函子?诚然,在这种情况下,使用函数指针模板参数的解决方案应该更小更快,但您可以使用一种语法,让Pair1stFunc2获取两个模板类型参数(P和F)并存储类型为F的成员F(对于函数指针情况,可以在1-arg的构造函数中填充)。然后操作符()(lhs,rhs)可以说“return f(lhs.first,rhs.first);”。实际上提出了三个模板,但它们具有相似的语法。Pair1stFunc2、Pair1stFunc2和Pair1stFunc2。它们的运算符()非常相似。@MSalters:啊,谢谢+1对于三种情况中的第一种,它肯定会提高函数指针情况的速度(直接调用,甚至可能是内联调用,而不是间接调用)。这是可行的,但模板参数在这里实际上是不必要的,因为您只将F称为“F”-参见Martin York的答案,这也适用于非模板比较器。boost mpl lambda表达式在这里很方便。只需传递std::less,您就可以编写“typename F”,然后执行typename mpl::apply::type F;相反,为了得到一个std::less,我觉得它非常好,特别是当您有一些模板可以接受额外的可选参数(如std::vector template)时,您只需传递std::vector+1即可。这比unwesel的解决方案更通用,因为它也适用于非模板比较器。
template<typename P, bool (*F)(P,P)> struct Pair1stFunc2 { ... }
typename F::result_type operator()(const P &lhs, const P &rhs) const
{ return F()(lhs.first, rhs.first); }
#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
}