如何检查函数参数的类型?

Jar*_*ock 5 c++ templates parameter-passing c++11

我有一个应用程序,我正在构建一个函数,marshal_and_applyf使用一些参数调用其他函数(或函子).marshal_and_apply的工作是根据参数的类型对参数应用一些特殊的编组f.

如果一个f的参数是一种特殊类型的,marshal_me<T>,然后marshal_and_apply将它传递给元帅之前通过一些特殊分配的存储参数f.为了执行分配,必须知道所有参数的存储要求,marshal_and_apply然后才能对其进行编组.


一些例子:

template<typename Function, typename... Args>
void marshal_and_apply(Function f, Args... args);

void func1(int x, int y);
void func2(marshal_me<int> x, int y);
void func3(marshal_me<int> x, marshal_me<int> y, marshal_me<int> z);

// this call would be equivalent to:
// func1(7,13)
marshal_and_apply(func1, 7, 13);

// this call would be equivalent to:
// auto storage = my_allocator(sizeof(int));
// auto x = marshal_me<int>(7, storage);
// func2(x, 13);
marshal_and_apply(func2, 7, 13);

// this call would be equivalent to:
// auto storage = my_allocator(sizeof(int) + sizeof(int) + sizeof(int));
// auto x = marshal_me<int>(7, storage);
// auto y = marshal_me<int>(13, storage + sizeof(int));
// auto z = marshal_me<int>(42, storage + sizeof(int) + sizeof(int));
// func3(x,y,z);
marshal_and_apply(func3, 7, 13, 42);
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,似乎marshal_and_apply需要一种机制来检查f参数的类型.我怀疑这通常是不可能的,但是有可能识别一组特殊类型(在这种情况下marshal_me<T>)是否可以转换为特定参数的类型.

我应该如何建造marshal_and_apply

Ker*_* SB 4

也许是这样的:

template<typename Function, typename... Args>
void marshal_and_apply(Function f, Args &&... args)
{
    f(InspectAndModify<Args>::process(sizeof...(Args), std::forward<Args>(args))...);
}
Run Code Online (Sandbox Code Playgroud)

现在定义:

template <typename T> struct InspectAndModify
{
    static T&& process(unsigned int N, T && t)
    {
        return std::forward<T>(t);
    }
};

template <typename T> struct InspectAndModify<marshal_me<T>>
{
     static T&& process(unsigned int N, marshal_me<T> && m)
     {
         /* ... */
     }
};
Run Code Online (Sandbox Code Playgroud)

完全不同的东西:这种方法首先剖析函数签名,然后对每对类型执行“静态转换”,这是您可以插入专业化的地方marshal_me

template <typename T> struct marshal_me { marshal_me(T) { } };

template <typename To, typename From> struct static_transform;

template <typename T> struct static_transform<T, T>
{
  static T go(T t) { return t; }
};

template <typename T> struct static_transform<T, T&>
{
  static T go(T & t) { return t; }
};

template <typename T> struct static_transform<marshal_me<T>, T>
{
  static marshal_me<T> go(T && t) { return std::forward<T>(t); }
};

template<typename T, typename... Args>
struct marshal_impl
{
  template <typename ...Urgs>
  static T go(T(*f)(Urgs...), Args &&... args)
  {
    return f(static_transform<Urgs, Args>::go(std::forward<Args>(args))...);
  }
};

template<typename Function, typename... Args>
void marshal_and_apply(Function f, Args &&... args)
{
  marshal_impl<void, Args...>::go(static_cast<typename std::decay<Function>::type>(f),
                                  std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)