【问题标题】:Passing condition as parameter传递条件作为参数
【发布时间】:2011-03-20 10:28:45
【问题描述】:

首先解释一下我要做什么:

void Foo(int &num, bool condition);

Foo(x, x > 3);

这段代码基本上会在调用函数之前评估条件的布尔值,然后传递纯真或假。我正在寻找一种让它通过条件本身的方法,所以我可以这样做:

void Foo(int &num, bool condition)
{
    while(!condition)
    {
        num = std::rand();
    }
}

我知道可以通过传递包含条件的字符串并解析后者来解决问题,我现在正在处理它,但我发现它的效率相当低。接受的答案将是除解析包含条件的字符串之外的任何其他方式解释解决方案的答案,或者澄清这种传递条件的方式是不可能的答案。

提前致谢

【问题讨论】:

  • 是否有更大的图景让我们可以在真实情况下看到Foo(假装它按你的意愿工作)?另外,当x 是引用时,您将其作为参数传递,而不是x 的地址。
  • 如果是std::rand() 请注意它返回int 并且不接受任何参数。
  • 是的,我没有检查它,我只是写它来说明事情应该如何工作。我真的很抱歉代码很可笑,但我直接在这里写了几分钟。 @GMan - 我可以复制和粘贴代码,但它可能会错过一些部分,所以我只是想给出这个想法。只要不尊重条件,它应该做的是一次又一次地要求用户输入。
  • 不会有每个 Foo 调用。相反,该函数应该运行一个 while 循环来检查条件,并一遍又一遍地询问输入,就像我在上面的评论中所说的那样。

标签: c++ parameter-passing


【解决方案1】:

您应该做的是创建一个测试您的条件的函数,然后将指向该函数的指针作为参数传递。有关如何执行此操作的详细信息/教程,请参阅http://www.cprogramming.com/tutorial/function-pointers.html

【讨论】:

  • 但是使用函数指针,您还需要传递边界或为所需的每个边界创建一个函数 - 普通函数不携带任何状态。
  • 是的,这正是我应该对字符串解析做的事情。还是我错过了什么?
【解决方案2】:

改为将函数传递给Foo。然后,您可以通过等待调用该函数来“延迟”表达式的执行。

【讨论】:

    【解决方案3】:

    执行此操作的可行方法是将仿函数(以及行为类似于函数的对象)传递给被调用函数,被调用函数将调用仿函数以在循环的每次迭代中重新评估条件。

    解析字符串不起作用;被调用函数无权访问调用函数的局部变量。

    【讨论】:

    • 字符串方法是基于它用于用户的数字输入这一事实,因此只有一个变量需要检查,可以作为参考传递,如果输入则分配给结果是在条件方面。否则函子就是我需要的,谢谢,投票。
    【解决方案4】:

    这称为函数式编程。

    这里是 sn-p 使用 boost::phoenix http://www.boost.org/doc/libs/1_43_0/libs/spirit/phoenix/doc/html/phoenix/starter_kit.html:

    using namespace boost::phoenix;
    
    Foo(x, (cref(x) < 3));
    // (cref(x) < 3) is expression that creates function object
    
    template<class C> // condition is a monster, make it generic
    void Foo(int &num, C condition)
    {
        while(!condition()) // notice you call condition as function
        {
            rand(num);
        }
    }
    

    【讨论】:

      【解决方案5】:

      正如其他人所说,将仿函数对象传递给 Foo()。 STL 通常使用这种方法。例如:

      template< class Func >
      void Foo(int &num, Func condition) 
      { 
          while(!condition()) 
          { 
              rand(num); 
          } 
      } 
      
      struct GreaterThanThree
      {
          int& _num;
          GreaterThanThree(int &num) : _num(num) {}
          bool operator()() const { return (_num > 3); }
      };
      
      Foo(x, GreaterThanThree(x)); 
      

      【讨论】:

      • 好吧,我不仅只使用大于三种情况,因为这意味着是一个包含常用条件输入的库。否则,我对 C++ 的高级可能性仍然很陌生,所以我得问一下 GreaterThanThree 结构代表什么(它不是通常的结构)。或许你可以提供一个链接来参考这些结构或类似的东西?
      • @Johnny:它是一个函子。 @Remy:为了让函子具有可变状态,Foo 应该引用 Func&amp; condition
      • @rwong:当然,如果您需要多次传入同一个函子对象。不过,这并不常见。我只见过与临时实例一起使用的仿函数,就像我展示的那样。
      【解决方案6】:

      一个使用标准库的例子functor

      #include <functional>
      
      template<class UnaryPred> void func(int& num, UnaryPred predicate) {
          while(!predicate(num)) num = std::rand();
      }
      
      void test() {
          int i = 0;
          func(i, std::bind1st(std::greater<int>(), 3));
      }
      

      请参阅&lt;functional&gt; 上的文档,了解 C++ 已经为您提供的开箱即用功能。

      如果您的编译器有足够的支持(例如 GCC 4.5 或 VC10),您也可以选择 lambda functions。例如。使用与上面相同的func()

      func(i, [](int num) { return num > 3; });
      

      【讨论】:

      • 这很可能正是我所需要的,并且很可能是一个公认的答案,只是我想检查一下,看看效果如何。关于lambda函数(我用的是VC10),如何在函数中调用?
      • 与第一个示例中的 func() 完全相同:predicate(someNumber)。 lambda 表达式还会在后台生成一个仿函数,只是编译器会为您完成它,您会得到更好的语法。
      • 哦,对不起,我以为后面的代码是独立于上面的代码的。所以它只是函数的简化调用?谢谢!
      • 是的,基本上第二个例子只是第一个例子的一个更简单的版本。参见例如here 了解有关 lambda 的更多信息。
      • 我在下一个代码中突出显示的行有错误,介意你看一下吗? pastebin.com/YzGMPzFz
      【解决方案7】:

      你可以在没有模板或提升的情况下做到这一点(一个评论者称之为“C 风格”,我想这是正确的)。

      /* have Foo take a pointer to a function that returns bool */
      void Foo(int &num, bool (*fcn)(int))
      {
          while(!fcn(num))
          {
              num = std::rand();
          }
      }
      
      /* You can have all the Comparators you want, 
         as long as they have the same signature */
      bool ComparatorOne(int x) { return x > 3 ? true : false; }
      
      bool ComparatorTwo(int x) { return x < 10 ? true : false; }
      
      /* and this is how you call it */
      int n;
      Foo(n, ComparatorOne);
      Foo(n, ComparatorTwo);
      

      编辑

      请注意,您的 Comparator 可以采用不同的参数集,只要它们是一致的。

      【讨论】:

      • 很抱歉我的问题不清楚,但我需要它用于任何类型的条件,不仅适用于整数。应该是通用的无论如何,感谢您提供此类解决方案的提示和示例,请投票!
      • 这是一种 C 风格的解决方案,而不是 C++ 解决方案。 C++ 将使用函子或 lambda(如果您的编译器支持它们)。
      • 我同意这是一个 C 风格的解决方案,但它有效且易于理解。
      猜你喜欢
      • 2011-11-02
      • 1970-01-01
      • 2017-07-21
      • 2013-01-16
      • 2022-01-14
      • 1970-01-01
      • 1970-01-01
      • 2013-11-04
      • 1970-01-01
      相关资源
      最近更新 更多