How to inspect the types of a function's parameters?

霸气de小男生 提交于 2019-12-21 16:59:04

问题


I have an application where I'm building a function, marshal_and_apply, which calls some other function (or functor), f with some arguments. marshal_and_apply's job is to apply some special marshaling for the arguments depending on the type of f's parameters.

If one of f's parameters is of a special type, marshal_me<T>, then marshal_and_apply will marshal the parameter through some specially allocated storage before passing it to f. In order to perform the allocation, the storage requirements of all the parameters must be known to marshal_and_apply before any can be marshaled.


Some examples:

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);

To solve this problem, it seems that marshal_and_apply requires a mechanism to inspect the types of f's parameters. I suspect this isn't possible in general, but it may be possible to recognize whether one of a special set of types (in this case, marshal_me<T>) is convertible to the type of a particular parameter.

How should I build marshal_and_apply?


回答1:


Maybe something like this:

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

Now define:

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)
     {
         /* ... */
     }
};

Something completely different: This approach first dissects the function signature, and then performs a "static transform" on each pair of types, which is where you can insert the marshal_me specialization:

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)...);
}


来源:https://stackoverflow.com/questions/8827171/how-to-inspect-the-types-of-a-functions-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!