首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Lambda作为默认参数失败

Lambda作为默认参数失败
EN

Stack Overflow用户
提问于 2015-05-14 22:38:02
回答 2查看 1.2K关注 0票数 19

我在使用clang和gcc的最新版本时遇到一个错误,代码如下:

代码语言:javascript
复制
int main() {
    auto lambda = [] (auto = [] {}) {};
    lambda();
}

Clang给出了错误:

代码语言:javascript
复制
prog.cc: In function 'int main()':
prog.cc:3:12: error: no match for call to '(main()::<lambda(auto:1)>) ()'
     lambda();
            ^
prog.cc:2:35: note: candidate: template<class auto:1> main()::<lambda(auto:1)>
     auto lambda = [] (auto = [] {}) {};
                                   ^
prog.cc:2:35: note:   template argument deduction/substitution failed:
prog.cc:3:12: note:   couldn't deduce template parameter 'auto:1'
     lambda();
            ^

为什么这会失败?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-14 22:42:33

auto的类型推导不考虑默认参数。

票数 22
EN

Stack Overflow用户

发布于 2015-05-14 23:13:29

模板函数(或方法)不会从默认参数中推导出它们的类型参数,带有auto参数的闭包只是一个带有模板方法的对象。

这使得模板函数有一个默认的lambda有点烦人。

一种方法是键入erase调用一个对象,而不存储它,如下所示:

代码语言:javascript
复制
#include <utility>
#include <type_traits>
#include <memory>

template<class Sig>
struct function_view;

template<class R, class...Args>
struct function_view<R(Args...)>{
  void* state;
  R(*f)(void*, Args&&...);

  template<class F, class=std::enable_if_t<std::is_convertible<std::result_of_t<F&(Args...)>,R>{}>>
  function_view( F&& fin ):
    state(const_cast<void*>(static_cast<void*>(std::addressof(fin)))),
    f( [](void* state, Args&&...args)->R{
      F&& f = std::forward<F>(*static_cast<std::decay_t<F>*>(state));
      return f(std::forward<Args>(args)...);
    })
  {}
  function_view( R(*fin)(Args...) ):
    state(fin),
    f( fin?+[](void* state, Args&&...args)->R{
      R(*f)(Args...) = static_cast<R(*)(Args...)>(state);
      return f(std::forward<Args>(args)...);
    }:nullptr)
  {}
  explicit operator bool(){return f;}
  function_view():state(nullptr),f(nullptr){}
  function_view(std::nullptr_t):function_view(){}
  R operator()(Args...args)const{
    return f(state, std::forward<Args>(args)...);
  }
};
template<class...Args>
struct function_view<void(Args...)>{
  void* state;
  void(*f)(void*, Args&&...);

  template<class F, class=std::result_of_t<F&(Args...)>>
  function_view( F&& fin ):
    state(const_cast<void*>(static_cast<void*>(std::addressof(fin)))),
    f( [](void* state, Args&&...args){
      F&& f = std::forward<F>(*static_cast<std::decay_t<F>*>(state));
      f(std::forward<Args>(args)...);
    })
  {}
  function_view( void(*fin)(Args...) ):
    state(fin),
    f( fin?+[](void* state, Args&&...args){
      void(*f)(Args...) = static_cast<void(*)(Args...)>(state);
      f(std::forward<Args>(args)...);
    }:nullptr)
  {}

  explicit operator bool(){return f;}
  function_view():state(nullptr),f(nullptr){}
  function_view(std::nullptr_t):function_view(){}
  void operator()(Args...args)const{
    f(state, std::forward<Args>(args)...);
  }
};

int main() {
  auto f = [] (function_view<void()> x=[]{}) {
    x();
  };
  f();
}

因为这只适用于函数指针,而且我对使用gcc内联简单的函数指针有很好的经验,所以它可能没有std::function那么高的性能影响。与std::function不同的是,它不涉及虚拟表或堆分配。

live example

对于非lambda,您可以这样做:

代码语言:javascript
复制
template<class X=function_view<void()>>
void f( X&& x=[]{} ) {
  x();
}

如果你传递的是一个参数,它就会推导出来,如果你不传递,它就会变成一个无用的函数。你也可以这样做:

代码语言:javascript
复制
struct do_nothing {
  template<class...Args>
  void operator()(Args&&...)const{}
};

template<class X=do_nothing>
void f( X&& x=do_nothing{} ) {
  x();
}

这可能更容易优化。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30240131

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档