当前位置: 首页 > 知识库问答 >
问题:

为什么非捕获lambda不能被默认构造,并且有可能解决这个问题吗?

茅星雨
2023-03-14

可以使用lambda的类型作为模板参数,例如

template<typename InArg, typename Function>
class selfCompose {
  Function f;
 public:
  selfCompose(Function f): f(f) {}
  auto operator() (InArg x) -> decltype(f(f(x))) {
    return f(f(x));                              }
};

int main() {
  auto f = [](int x){return x*x;};
  std::cout << selfCompose<int, decltype(f)>(f)(4)  //  yields (4²)² = 256
            << std::endl;
  return 0;
}

但是,重复使用f是一种冗余。我们可以省略将lambda的类型作为模板传递(将其转换为合适的std::function(在失去多态性的情况下–但是C lambda无论如何都不是参数多态的)),但是我有一个应用程序,我更希望不必将其值传递给构造函数(因为我想使用我的类的初始化本身作为模板参数,其中需要一个特定的构造函数签名)

template<class InArg, class Function>
class selfCompose {
  Function f;
 public:
  selfCompose() {}  // default constructor for f
  auto operator() (InArg x) -> decltype(f(f(x))) {
    return f(f(x));                              }
};

int main() {
  auto f = [](int x){return x*x;};
  std::cout << selfCompose<int, decltype(f)>()(4) << std::endl;
  return 0;
}

但这不会编译,因为lambda有一个已删除的默认构造函数。这对于捕获lambda来说当然是不可避免的,但是对于像我的示例中这样的简单对象,这对我来说没有多大意义:它们不需要引用任何局部变量。

是否有其他方法获得此功能,或者我是否必须将lambda old时髦地定义为命名类?

struct myFun {
  auto operator() (int x) -> int {return x*x;}
};

(当然,我想使用的lambda函数没有x那么简单→ x²,因此仅从几个标准函数类中进行选择是不够灵活的)

共有3个答案

暨正真
2023-03-14

本杰明已经为你的案子提出了一个很好的解决办法。你可以用这个。

我的解决方案只是Benjamin答案的一个改进版本,您不必指定lambda参数类型。因此,与其写这封信:

make_selfCompose<int>(f)(4); //Benjamin's solution

你可以这样写:

make_selfCompose(f)(4); //improved - absence `int` template argument.

make_selfCompose推导lambda参数类型本身。

对于此解决方案,让我们先编写函数\u traits类模板,如下所示:

#include <tuple>

template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};

template <typename C, typename R, typename... A>
struct function_traits<R(C::*)(A...) const>
{
   template <size_t i>
   struct arg
   {
      typedef typename std::tuple_element<i, std::tuple<A...>>::type type;
   };
};

然后这里是make_selfCompose的改进版本:

template<typename Fun> //<--- now it has one template parameter
selfCompose<typename function_traits<Fun>::template arg<0>::type, Fun>
make_selfCompose(Fun f)
{
  typedef typename function_traits<Fun>::template arg<0>::type InArg; //deduce it
  return selfCompose<InArg, decltype(f)>(f);
}

以下是测试程序:

int main() {
  auto f = [](int x){return x*x;};
  std::cout << make_selfCompose(f)(4)  //notice the relief here!
            << std::endl;
  return 0;
}

查看在线演示

希望有帮助。:-)

甘君之
2023-03-14

如果将selfCompose设置为多态,则无需显式传递参数类型或检查存储的函子类型。后者意味着它还能够处理多态函子。

template<typename Functor>
struct self_compose_type {
    // Omitting encapsulation for brevity
    Functor functor;

    // It is possible to overload operator() to deal
    // with all cv and ref qualifiers combinations
    template<typename... T>
    auto operator()(T&&... t)
    // Don't use std::result_of for the return type
    -> decltype( std::declval<Functor&>()(std::declval<T>()...) )
    { return functor(std::forward<T>(t)...); }
};

template<typename Functor>
self_compose_type<Functor>
self_compose(Functor&& functor)
{ return { std::forward<Functor>(functor) }; }

// C++03 style:
template<typename Functor>
self_compose_type<typename std::decay<Functor>::type>
make_self_compose(Functor&& functor)
{ return { std::forward<Functor>(functor) }; }

无需将运算符()设为变量,如果愿意,可以将其设为只接受一个参数。

谭坚诚
2023-03-14

您可以遵循像make_pairmake_shared这样的函数示例:

template<typename InArg, typename Function>
selfCompose<InArg, Function> make_selfCompose(Function f)
{
  return selfCompose<InArg, decltype(f)>(f);
}

int main() {
  auto f = [](int x){return x*x;};
  std::cout << make_selfCompose<int>(f)(4)
            << std::endl;
  return 0;
}
 类似资料:
  • 这个问题与前一个问题相关,在前一个问题中,我们注意到init捕获lambdas与Boost的范围和迭代器不兼容,因为一些相当模糊且嵌套很深的故障可能很难通过破解Boost来解决。射程源。 接受的答案建议将lambda存储在对象中。为了避免潜在的函数调用开销,我编写了两个函数对象,可以作为潜在的解决方法。它们在下面的代码中被称为和 不使用和编译行,并正确打印行的的实例。 然而,标准草案提到 5.1.

  • 问题内容: 为什么这段代码会引发SyntaxError? 尽管以下代码段运行时没有可见错误: 问题答案: 必须将所有必需的参数放在任何默认参数之前。仅仅是因为它们是强制性的,而默认参数不是必需的。从语法上讲,如果允许使用混合模式,解释器将 无法 决定哪些值与哪些参数匹配。如果参数的输入顺序不正确,则会引发A : 让我们使用您的函数来查看关键字参数。 假设其允许声明函数如上,然后使用上述声明,我们可

  • 我有一个扩展JTextField的类,我想让CTRL-Shift-O做一些事情。我一直在听 在e.isControlDown()和e.isShiftDown()的帮助下,这种方法运行良好。但我注意到字段中的文本也在从左边向右边移动。显然,这是JTextField的默认行为。所以我在So上找到了这个线程,它似乎很有帮助: 如何禁用JTextField中的默认textfield快捷方式 尽管Syste

  • 这是一个骇人听闻的问题:爱丽丝是一个幼儿园老师。她想给班上的孩子们一些糖果。所有的孩子坐成一行(他们的位置是固定的),每个人根据他(她)在班上的表现有一个评级分数。爱丽丝想给每个孩子至少一颗糖。如果两个孩子挨着坐,那么评分较高的那一个必须得到更多的糖果。爱丽丝想省钱,所以她需要尽量减少给孩子们的糖果总数。 测试数组:n=10,n个元素为[2 4 2 6 1 7 8 9 2 1]。我得到的答案是18

  • 在C#中,当我创建一个空类时,它提供了一个默认的构造函数,但是当我提供一个带有参数的构造函数时,默认的构造函数不再被创建。 我的问题是: 为什么编译器不再给我默认的构造函数呢 这些问题来自于WCF,我需要默认构造函数,但也希望能够为构造函数提供值,并且不必每次都放置默认构造函数,而且我不认为未使用的默认构造函数会使很多开销。

  • 由于找不到文件,send方法返回null BufferedReader。Eclipse只是说有一个NullPointerException是因为print方法,但是当我移除所有try/catch语句时,Eclipse说我需要编写方法抛出IOException或FileNotFoundException,它也允许我这样做,如果我不这样做,它就抛出一个FileNotFoundException。然而,