Cast函数类型对不同类型的参数是可转换的

时间:2015-04-12 19:00:36

标签: c++ templates function-pointers

我正在为可调用类型(函数,仿函数等指针)编写一个包装类。我想实现类似std :: function的东西。

我将指针定义为函数的构造函数:

template <typename Ret, typename... Args>
class function<Ret(Args...)>
{
public:
    function(Ret (func)(Args...))
    {
        m_fn_ptr = func;
    }
}

现在,让我们假设我想要像我这样使用我的课程:

int int_function(int n)
{
    return n;
}

function<int(short)> wrapper(&int_function); // compile error

尽管short是隐式可转换为int编译器,但不能推导出模板参数并调用适当的构造函数。

然后我试了一下:

template <typename FRet, typename... FArgs>
function(FRet (func)(FArgs...))
{
    m_fn_ptr = static_cast<Ret (*f)(Args...)>(func);
}

但是我得到了无效的静态演员。

我该如何解决?

3 个答案:

答案 0 :(得分:1)

super_func是一个函数对象,没有可以转换为任何兼容调用签名的状态。

template<class T>using type=T;

template<class Sig, Sig* func>
struct super_func;
template<class R, class...Args, R(*func)(Args...)>
struct super_func<R(Args...), func> {
  using Sig = R(Args...);
  using pSig = Sig*;
  template<class R2, class...Args2, class=std::enable_if_t<
    std::is_convertible<
      std::result_of_t<pSig(Args2...)>,
      R2
    >{}
    && !std::is_same<R2, void>{}
  >>
  constexpr operator type<R2(Args2...)>*() const {
    return [](Args2...args)->R2{
      return func(std::forward<Args2>(args)...);
    };
  }
  template<class...Args2, class=std::enable_if_t<
    std::is_same<
      std::result_of_t<pSig(Args2...)>,
      R
    >{}
  >>
  constexpr operator type<void(Args2...)>*() const {
    return [](Args2...args)->void{
      func(std::forward<Args2>(args)...);
    };
  }
  constexpr operator pSig() const {
    return func;
  }
  constexpr R operator()(Args...args)const{
    return func(std::forward<Args>(args)...);
  }
};

live examplesuper_func是无国籍人。要在函数foo上使用它,请执行:

super_func< decltype(foo), &foo > super_foo;

并且你得到一个可调用的无状态空对象,其行为与foo非常相似,除了你可以将它指定给指向任何兼容函数指针的指针,它会立即生成它&#34;&#34;在编译时。

可以将super_foo输入您的功能对象。

在没有外部帮助的情况下,即时执行此操作并不起作用,因为我们需要foo成为真正的静态信息。当它变成一个变量时,做无状态的为时已晚,所以我们不能使用lambda技巧(没有额外的pvoid)来生成我们想要的确切签名的函数指针。

你可以做一个宏:

#define SUPER(X) super_func< decltype(X), &X >{}

然后使用function

创建function<double()> f(SUPER(foo));对象

另一种方法是存储额外指针的状态,并创建最快的代表&#34;风格类型擦除。 (该术语可以用Google搜索其中一个实现,每个实现都比上一个快。)

答案 1 :(得分:0)

  

我该如何解决?

创建wrapper时使用正确的类型。

而不是使用

function<int(short)> wrapper(&int_function);

使用

function<int(int)> wrapper(&int_function);

请注意,使用intshort实例化的类模板是非常不同的类型,并且不能相互转换。

template <typename T> struct Foo {};

Foo<int> a;
Foo<short> b = a; // Not OK.

Foo<short> c;
Foo<int> d = c; // Not OK.

答案 2 :(得分:0)

您的function构造函数需要一个指向函数的指针,该函数需要short,而不是int。修复是为它提供这样的功能。最简单的方法是使用带有空捕获列表的lambda,它可以隐式转换为函数指针:

function<int(short)> wrapper( [](short s) { return int_function(s); } );