【问题标题】:C++11 Lambda Template InferingC++11 Lambda 模板推断
【发布时间】:2012-09-21 09:10:52
【问题描述】:

所以我有以下代码:

#include <iostream>

template <typename T>
class funcky
{
  public:
    funcky(char const* funcName, T func)
      : name(funcName), myFunc(func)
    {
    }

  //private:
    char const* name;
    T myFunc;
};

#if 0
int main(void)
{
  char const* out = "nothing";

  // requires template args
  funcky test("hello", [&](int x, int y) -> int
  {
    out = "YES";
    return x + y;
  });

  std::cout << test.name << " = " << test.myFunc(1, 2) << std::endl;
  std::cout << test.name << " = " << out << std::endl;

  return 0;
}

int main2(void)
{
  funcky<void(*)(void)> test("hello", [&, this](void) -> void
  {
    std::cout << this->name << std::endl;
  });

  test.myFunc();

  return 0;
}
#endif

int main(void)
{
  char const* out = "nothing";

  auto myFunc = [&](int x, int y) -> int
  {
    out = "YES";
    return x + y;
  };
  funcky<decltype(myFunc)> test("hello", myFunc);

  std::cout << test.name << " = " << test.myFunc(1, 2) << std::endl;
  std::cout << test.name << " = " << out << std::endl;

  return 0;
}

顶部块是一个函数持有者,其中包含一个 lambda 及其名称。

接下来是我想在 API 方面使用的,但由于没有指定模板参数而失败。

之后,我想知道是否可以在未在其中声明的 lambda 中使用特定类型(例如 funcky)的“this”。一厢情愿。

最后是编译但在 funcky 构造函数和 decltype 之外使用 lambda 的代码。

在 C++11 中这样的事情是可能的吗?我如何完成所说的事情?

此外,除非它可以具有相同的 API,否则尽量不要猜测我在做什么,就好像我不能那样做,我会用更简单的方式重写它。这不值得。

【问题讨论】:

    标签: c++ templates lambda c++11


    【解决方案1】:

    如果您想为用户提供一种向您的类提供回调的方法,最好使用std::function,因为在函数/仿函数类型上模板化类并不是一件非常有用的事情,正如你所经历的那样。

    问题在于您不能只接受任何东西。您应该对可以作为回调传递的内容有明确的要求,因为您应该知道以后要如何调用它。请参阅this,了解我为什么将构造函数设为模板。

    #include <functional>
    #include <utility>
    
    struct X{
      template<class F>
      X(F&& f) : _callback(std::forward<F>(f)) {} // take anything and stuff it in the 'std::function'
    
    private:
      std::function<int(int,int)> _callback;
    };
    
    int main(){
      X x([](int a, int b){ return a + b; });
    }
    

    但是,如果 不知道回调将如何被调用(例如,用户稍后传递参数),但您想支持这一点,请将您的类型模板化回调的签名

    #include <iostream>
    #include <functional>
    #include <utility>
    
    template<class Signature>
    struct X{
      template<class F>
      X(F&& f) : _callback(std::forward<F>(f)) {} // take anything and stuff it in the 'std::function'
    
    private:
      std::function<Signature> _callback;
    };
    
    int main(){
      X<int(int,int)> x1([](int a, int b){ return a + b; });
      X<void()> x2([]{ std::cout << "wuzzah\n";});
    }
    

    【讨论】:

    • 啊,所以没有办法两全其美,并让签名隐含或从 lambda 中计算出来?
    • @Jookia 不,这不会发生。您应该考虑可调用而不是 lambda。 Lambda 在任何方面都不是特别的。 struct try_to_deduce_a_signature_for_this_one { template &lt;typename T&gt; void f(T); };
    • @Jookia:decltype 无助于查找签名,最多只能帮助查找返回类型某些参数,也就是您(或用户)总是需要知道你想怎么称呼它。
    【解决方案2】:

    类似

    template<typename Functor>
    funcky<typename std::decay<Functor>::type>
    make_funcky(const char* name, Functor&& functor)
    { return { name, std::forward<Functor>(functor) }; }
    

    对以下方面有帮助:

    auto test = make_funcky("hello", [&](int x, int y) -> int
    {
        out = "YES";
        return x + y;
    });
    

    但是,在 lambda 表达式内 this 始终指代表达式外的直接 this。这不是对调用时存在的某些this延迟 引用——它不是隐式参数。因此,为它想要“另一种类型”是没有意义的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-25
      • 1970-01-01
      • 1970-01-01
      • 2022-12-02
      • 1970-01-01
      • 2013-12-05
      • 2023-03-31
      相关资源
      最近更新 更多