使用模板元编程执行过载解决

Perform overload resolution with template meta-programming

本文关键字:执行 解决 编程      更新时间:2023-10-16

受另一个问题的启发,我试图找到一种推导类型的方法给定用于调用的实际参数的重载成员函数该功能。以下是我目前所拥有的:

#include <type_traits>
template<typename F, typename Arg>
struct mem_fun_type {
  // perform overload resolution here
  typedef decltype(std::declval<F>()(std::declval<Arg>())) result_type;
  typedef decltype(static_cast<result_type (F::*)(Arg)>(&F::operator())) type;
};
struct foo {};
struct takes_two
{
  void operator()(int);
  void operator()(foo);
};
struct take_one {
  void operator()(float);
};
int main()
{
  static_assert(std::is_same<mem_fun_type<take_one, float>::type, 
                             void (take_one::*)(float)>::value, "Zonk");
  static_assert(std::is_same<mem_fun_type<takes_two, double>::type, 
                             void (takes_two::*)(float)>::value, "Zonk");
  return 0;
}

只要模板参数Arg与实际类型匹配static_cast会成功,但这只是过载分辨率(精确匹配)。是否可以执行完成模板元编程中的过载解决过程?

这纯粹是假设性的,不适用于现实世界。

这是我迄今为止最接近的方法:定义不同大小的函数返回表,结果是sizeof(select(...))接收指向要匹配的函数的指针。为了确保即使给定类中不存在函数,代码也会编译,可以使用单独的检查has_function

过载解决的结果在select<has_function<T>::value, T>::value中。

有了这段代码,您甚至可以"解析"数据成员,而不仅仅是函数,这只是为select函数设置正确参数的问题。

然而,这里有一个不足——重载解析不在函数参数上,而是在函数类型上。这意味着不会发生通常的参数类型转换。

  // Verify the name is valid
  template <typename T>
  struct has_function
  {
    struct F {int function;};
    struct D : T, F {};
    template <typename U, U> struct same_;
    template <typename C> static char(&select_(same_<int F::*, &C::function>*))[1];
    template <typename> static char(&select_(...))[2];
    enum {value = sizeof(select_<D>(0)) == 2};
  };
  // Values to report overload results
  enum type { none=1 , function_sz_size_t , function_sz , function_string };
  template <bool, typename R> struct select;
  template <typename R> struct select<false, R>
  {
    enum {value = none};
  };
  template <typename R> struct select<true, R>
  {
    // Define your overloads here, they don't have to be templates.
    template <typename Ret, typename Arg> static char(&select_(Ret (R::*)(const char*, Arg)))[function_sz_size_t];
    template <typename Ret, typename Arg> static char(&select_(Ret (R::*)(Arg)))[function_sz];
    template <typename Ret> static char(&select_(Ret (R::*)(std::string)))[function_string];
    template <typename Ret> static char(&select_(Ret (R::*)(std::string&&)))[function_string];
    template <typename Ret> static char(&select_(Ret (R::*)(const std::string&)))[function_string];
    static char(&select_(...))[none];
    enum {value = sizeof(select_(&R::function))};
  };