【问题标题】:How to handle default value for a templated functor如何处理模板仿函数的默认值
【发布时间】:2011-10-11 12:21:18
【问题描述】:

给定一个这样的函数:

template<typename functor>
void foo(functor const& f)
{
    if (f)
        f(1, 2);
}

我希望能够分配一个默认值,其中f 可以设置为类似于NULL 的值。此外,对空函数进行虚假调用就足够了。有什么我可以使用(来自标准或boost-library)而不自己创建这样的东西吗?

【问题讨论】:

  • 你能澄清一下这个问题吗?因此,您想以两种方式调用foofoo(some_functor);foo();,在后一种情况下,您希望foo(); 什么都不做。但是为什么首先要打电话给foo();

标签: c++ templates functor


【解决方案1】:

使用空函子并用作默认模板参数。你不能使用像 NULL 这样的东西,因为你没有指针:

class X
{
    void operator()(...) {}
};

template <typename functor = X>
void foo(functor const& f = X())
{
    f(...);
}

【讨论】:

  • 我认为您也需要提供一个默认函数参数:foo(functor const &amp; f = X())
  • 我假设你的意思是template &lt;typename functor = X&gt; foo(functor const &amp; f = functor())。这也允许foo&lt;void(*)()&gt;()
  • 是的@KerrekSB,你是对的。我对类模板参数感到困惑。谢谢
  • @MSalters:哦,是的:f = functor()。谢谢!
  • 我不明白需要默认参数。如果你有时什么都不传递,而仿函数也不做任何事情,为什么首先调用foo
【解决方案2】:

要么编写一个什么都不做的重载,要么将一个无操作函子传递给foo

【讨论】:

    【解决方案3】:

    最简单的方法是创建一个不带参数的重载:

    template<typename functor>
    void foo()
    {
    }
    

    如果默认操作取决于模板参数,您将不得不明确提供它,因为编译器无法从中推断出它。如果没有,那么您甚至不需要将其设为模板。

    【讨论】:

      【解决方案4】:

      我不想使用重载函数。看来使用自己写的“nop-class”是最好的解决方案。

      struct nop
      {
          void operator()(...) const volatile {}
      };
      
      template<typename functor> 
      void foo(functor const& f = functor()) 
      {
          f(1, 2);
      }
      
      int main()
      {
          foo<nop>();
          return 0;
      }
      

      【讨论】:

      • 请注意,如果在实例化中为... 传递任何非平凡可复制的类型,则不能使用nop 的可变成员函数。
      【解决方案5】:

      在我期望函子不返回任何值的情况下,我将其用作插入式无操作。

      struct VoidNoOp {
          void operator()() const { }
          template<class A>
          void operator()(A a) const { (void)(a); }
          template<class A, class B>
          void operator()(A a, B b) const { (void)(a); (void)(b); }
          template<class A, class B, class C>
          void operator()(A a, B b, C c) const { (void)(a); (void)(b); (void)(c); }
      };
      

      这是任意数量参数的 C++11 变体:

      struct VoidNoOp {
          void operator()() const { };
          template<typename P1, typename... Params>
          void operator()(P1 p1, Params... parameters) {
              (void)(p1);             // we do this just to remove warnings -- requires the recursion
              operator()(parameters...);
          }
      };
      

      【讨论】:

        【解决方案6】:

        问题在于functor 是由调用者确定的类型,因此它可能没有默认构造函数,或者您依赖的任何其他功能来构建默认值。

        那么,你可以使用重载函数吗?

        template<typename functor>
        void foo(functor const& f)
        {
               f(1, 2);
        }
        
        template<typename functor>
        void foo()
        {
        }
        

        【讨论】:

          【解决方案7】:

          可以在运行时存储 NULL 的函数包装器是 std::function (C++11)boost::function

          #include <functional>
          #include <cstdio>
          
          void foo(std::function<void(int, int)> f)
          {
              if (f) {
                 f(1, 2);
              }
          }
          
          void print(int a, int b) { std::printf("%d %d\n", a, b); }
          
          int main()
          {
             foo(0);
             foo(print);
          }
          

          【讨论】:

          • 使用函数包装器在功能上是足够的,但性能损失是不合理的。还是谢谢。
          猜你喜欢
          • 1970-01-01
          • 2011-03-19
          • 1970-01-01
          • 2019-04-08
          • 2015-07-08
          • 2023-01-02
          • 1970-01-01
          • 2014-05-18
          • 2011-06-11
          相关资源
          最近更新 更多