【问题标题】:Deduce function parameters from a generic function/lambda [duplicate]从通用函数/ lambda 推导出函数参数
【发布时间】:2015-12-02 19:35:25
【问题描述】:

这是我目前拥有的

void test(int& i, float& f) {}

template <class... Ts, class F>
void update(F&& f)
{
  //Use Ts here
}

int main()
{
  update<int, float>(test);
}

但我需要使用&lt;int, float&gt; 显式调用更新,因为我想将其用于元编程。

如果可以从函数中自动推导出来就好了

void test(int& i, float& f) {}

template <class... Ts>
void update(std::function<void(Ts&...)> f)
{
   //use Ts here
}
int main()
{
  //error: no matching function for call to 'update'
  update(test);
}

【问题讨论】:

  • boost function traitsother function traits 可能会有所帮助。
  • 这个问题之前在stackoverflow上已经回答过好几次了。基本上编译器无法提前知道void(*)(int&amp;, float&amp;) 可以转换为std::function&lt;void(int&amp;, float&amp;)&gt;,因为它在推导出Ts... 之后才能看到function 特化的构造函数,但是没有办法提前推导出来(编译器都知道,std::function 的每个特化都可以从该函数指针转换)。

标签: c++ c++14


【解决方案1】:

只需提供一个转换重载:

#include <iostream>
#include <functional>

void test(int& i, float& f) {}


template <class... Ts>
void update(std::function<void(Ts&...)> f)
{
    //use Ts here
}

// this overload matches the function pointer and forwards the function
// pointer in a std::function as required
template<class... Ts>
void update(void (*fp)(Ts&...))
{
    update(std::function<void(Ts&...)>(fp));
}

int main()
{
    //error: no matching function for call to 'update'
    update(test);
}

【讨论】:

    【解决方案2】:

    当然可以:)

    考虑一下:

    #include <functional>
    
    int test(int& , float& ) { return 0;}
    double test2(char* ) { return 0; }
    
    template <class F>
    void update(F&& )
    {
      typedef typename F::result_type R;
    }
    
    template <class R, class... ARGS>
      auto make_function(R (*f)(ARGS...)) {
        return std::function<R (ARGS...)>(f);
    }
    
    int main()
    {
    
      update(make_function(&test));
      update(make_function(&test2));
    }
    

    【讨论】:

      【解决方案3】:

      当参数是函数指针时,这很容易做到:只需添加这个重载:

      template <class R, class... Ts>
      void update(R (*f)(Ts...)) {
          update(std::function<R(Ts...)>(f));
      }
      

      如果你得到一些任意的东西,那是不可能的:

      struct foo {
          template <typename T0, Typename T1>
          void operator()(T0, T1);
      };
      

      要推导出哪些参数?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-19
        • 1970-01-01
        • 1970-01-01
        • 2015-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-25
        相关资源
        最近更新 更多