【问题标题】:templates and function objects - c++模板和函数对象 - C++
【发布时间】:2010-07-22 11:15:34
【问题描述】:

我对这门课有疑问。
目标是使主要功能正常工作。我们应该实现“And”函数对象,这样代码才能工作。我找不到我们的解决方案有什么问题。
(解决方案开始和结束在“main”函数之前的代码中用cmets标记)
你能帮忙吗?
谢谢

#include <iostream>
#include <algorithm>

using namespace std;

class NotNull
{
    public:
    bool operator()(const char* str) {return str != NULL;}
};

class BeginsWith
{
    char c;
    public:
    BeginsWith(char c) : c(c) {}
    bool operator()(const char* str) {return str[0] == c;}
};

class DividesBy {
    int mod;
    public:
    DividesBy(int mod) : mod(mod) {}
    bool operator()(int n) {return n%mod == 0;}
};

//***** This is where my sulotion starts ******

template <typename Function1, typename Function2, typename T>
class AndFunction
{
    Function1 f1;
    Function2 f2;
    public:
    AndFunction(Function1 g1, Function2 g2) : f1(g1), f2(g2) {}
    bool operator()(T t)
    {
        return (f1(t) && f2(t));
    }
};

template <typename Function1, typename Function2, typename T>
AndFunction <Function1, Function2, T>

bool And(Function1 f1, Function2 f2)
{
    return AndFunction<Function1, Function2, T>(f1, f2);
}

//***** This is where my sulotion ends ******

int main(int argc, char** argv)
{
    int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    char* strings[4] = {"aba", NULL, "air", "boom"};
    cout << count_if(array,array+10,And(DividesBy(2),DividesBy(4))) << endl;
    // prints 2, since 4 and 8 are the only numbers which can be divided by
    // both 2 and 4.
    cout << count_if(strings,strings+4,And(NotNull(),BeginsWith('a'))) <<endl;
    // prints 2, since only "aba" and "air" are both not NULL and begin
    // with the character 'a'.
    return 0;
}

【问题讨论】:

  • 究竟是什么不起作用?我觉得奇怪的是,您将 t 传递给 operator bool 中的函数。
  • 一些注意事项: 1. Functors 通常继承自 std::unary_functionstd::binary_function 或定义 typedefs first_argument_type, second_argument_type, result_type 以使其与例如兼容。 Boost.Functions。 2. 迭代器以外的类对象通常是通过const引用来传递的。 3.operator() 通常是常量。 4. 字符文字是常量对象,不鼓励将它们转换为char*。 5. 函子NotNullBeginsWithDividesBy 也可以是泛型的。

标签: c++ templates function-object


【解决方案1】:

显然,您在创建仿函数时并不知道T 参数。您是否考虑过推迟在实际通话中引入 T(即,将 operator() 设为成员模板)?

【讨论】:

    【解决方案2】:

    在此处创建对象时,您没有调用重载的 () 运算符: return AndFunction&lt;Function1, Function2, T&gt;(f1, f2);(在; 之前需要())这段代码实际上甚至不应该编译,因为目前它返回一个对象,而不是一个布尔值。


    编辑:正如所指出的,函数 (bool And(Function1 f1, Function2 f2) ) 不能返回 bool,而是一个函数对象,供 count_if 通过重载的 () 运算符调用

    【讨论】:

    • 其实它不应该返回bool,而是函数对象。
    • 是的,我只是在定义bool And(Function1 f1, Function2 f2),所以猜猜这​​个错误是倒置的(如果真的可以倒置错误?:P)
    【解决方案3】:

    从技术上讲,如果您希望将 unary_functionbinary_function 类与 STL 算法搭配使用,那么您应该使用它们作为父类。这里:

    template<typename Func1, typename Func2,typename T>
    struct AndFunction : public unary_function<T,bool>{
        AndFunction(Func1 _func1, Func2 _func2) 
            : _myFunc1(_func1),
            _myFunc2(_func2){}
    
        bool operator()(T _t){
            return _myFunc1(_t) && _myFunc2(_2);
        }
    
    private:
        Func1 _myFunc1;
        Func2 _myFunc2;
    };
    

    在你的情况下你需要做

    template<typename Func1, typename Func2, typename T> 
    AndFunction<Func1, Func2, T> And(Func1 _func1, Func2 _func2){
        return AndFunction<Func1,Func2,T>(_func1,_func2);
    };
    

    这样您就不会将操作符与对象创建混淆,并且您可以指定如何接收函数指令。

    另一方面,你的 main 的工作方式我认为你真的只是想要

    struct And : public binary_function<bool, bool, bool>{
        bool operator()(bool _1, bool _2){
            return _1 && _2;
        }
    };
    

    希望对您有所帮助。

    【讨论】:

      【解决方案4】:

      模板参数T无法推断,必须明确指定:

      template <typename T, typename Function1, typename Function2>
      AndFunction <Function1, Function2, T>
      And(Function1 f1, Function2 f2)
      {
          return AndFunction<Function1, Function2, T>(f1, f2);
      }
      
      //***** This is where my sulotion ends ******
      
      int main(int argc, char** argv)
      {
          int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
          char* strings[4] = {"aba", NULL, "air", "boom"};
          cout << count_if(array,array+10,And<int>(DividesBy(2),DividesBy(4))) << endl;
          // prints 2, since 4 and 8 are the only numbers which can be divided by
          // both 2 and 4.
          cout << count_if(strings,strings+4,And<const char*>(NotNull(),BeginsWith('a'))) <<endl;
          // prints 2, since only "aba" and "air" are both not NULL and begin
          // with the character 'a'.
          return 0;
      }
      

      jpalecek 的解决方案更好,工作原理如下:

      //***** This is where my sulotion starts ******
      
      template <typename Function1, typename Function2>
      class AndFunction
      {
          Function1 f1;
          Function2 f2;
          public:
          AndFunction(Function1 g1, Function2 g2) : f1(g1), f2(g2) {}
        template<typename T> bool operator()(T)
          {
              return (f1(t) && f2(t));
          }
      };
      
      template <typename Function1, typename Function2>
      AndFunction <Function1, Function2>
      And(Function1 f1, Function2 f2)
      {
          return AndFunction<Function1, Function2>(f1, f2);
      }
      
      //***** This is where my sulotion ends ******
      

      【讨论】:

        猜你喜欢
        • 2011-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多