Perform overload resolution with template meta-programming

允我心安 提交于 2019-12-21 20:23:12

问题


Inspired by another question I tried to find a way to deduce the type of an overload member function given the actual argument used to call that function. Here is what I have so far:

#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;
}

As long as the template parameter Arg matches the actual type the static_cast will succeed, but this is only the most trivial case of overload resolution (exact match). Is it possible to perform the complete overload resolution process in template metaprogramming?

This is purely hypothetical and not intended for real-world use.


回答1:


This is closest I came to it so far: define function returning tables of different sizes and your result is sizeof(select(...)) receiving pointer to function you want to match. To ensure that the code will compile even if function does not exist in given class, you can use separate check has_function.

Result of overload resolution is in select<has_function<T>::value, T>::value.

With this code you can even "resolve" data members, not just functions, it's only a question of making right parameter for select function.

However there is one deficiency here - overload resolution is not on function parameters, but on function type. Meaning none of usual parameter type conversions takes place.

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


来源:https://stackoverflow.com/questions/8935520/perform-overload-resolution-with-template-meta-programming

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