0

I did not write this code, I hope everyone can help me.

I have the following code, which can reasonably expand the parameters of ordinary functions.

I hope it can, expand, the constructor of the class.

#include <iostream>
#include <utility>
#include <vector>

namespace util {
template <typename ReturnType, typename... Args>
struct function_traits_defs {
  static constexpr size_t arity = sizeof...(Args);

  using result_type = ReturnType;

  template <size_t i>
  struct arg {
    using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
  };
};

template <typename T>
struct function_traits_impl;

template <typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(Args...)>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(*)(Args...)>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...)>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const&>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const&&>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile&>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile&&>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile&>
    : function_traits_defs<ReturnType, Args...> {};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile&&>
    : function_traits_defs<ReturnType, Args...> {};

template <typename T, typename V = void>
struct function_traits
    : function_traits_impl<T> {};

template <typename T>
struct function_traits<T, decltype((void)&T::operator())>
    : function_traits_impl<decltype(&T::operator())> {};

template <size_t... Indices>
struct indices {
  using next = indices<Indices..., sizeof...(Indices)>;
};
template <size_t N>
struct build_indices {
  using type = typename build_indices<N - 1>::type::next;
};
template <>
struct build_indices<0> {
  using type = indices<>;
};
template <size_t N>
using BuildIndices = typename build_indices<N>::type;

namespace details {
template <typename FuncType,
          typename VecType,
          size_t... I,
          typename Traits = function_traits<FuncType>,
          typename ReturnT = typename Traits::result_type>
ReturnT do_call(FuncType& func, const VecType& args, indices<I...>) {
  return func(args[I]...);
}
}  // namespace details

template <typename FuncType, typename VecType, typename Traits = function_traits<FuncType>>
auto unpack_caller(FuncType& func, const VecType& args) {
  return details::do_call(func, args, BuildIndices<Traits::arity>());
}
}  // namespace util

int func(int a, int b, int c) {
  return a + b + c;
}

int main() {
  std::vector<int> args = {1, 2, 3};

  int j = util::unpack_caller(func, args);
  std::cout << j << std::endl;

  return 0;
}

e.g By adding a class function in the form of a template, and automatically looking for the parameters of the constructor.

class foo
{
public:
    foo(uint32_t a, uint32_t b, uint32_t c){};
};

int main() {
      std::vector<int> args1 = {1, 2, 3};
    
      foo* f = util::unpack_caller<foo>(args);
    
      return 0;
    }
Zephyr
  • 1
  • 1
    A constructor doesn't have a return type. In addition, you [cannot take a constructor's address](https://stackoverflow.com/a/954565/8423261) either so there is no way for you to point to a constructor to call it from somewhere else. So, no, it is not possible unless you create a dummy helper function that does the same thing that the constructor does and use that instead. – Ruks Aug 03 '21 at 11:49
  • The purpose of executing the constructor is not to return the type. But for the new object, return the pointer address of the new object. Just like the rttr reflection library. – Zephyr Aug 03 '21 at 12:51

1 Answers1

1

This first argument of the unpack_caller method should be a callable object, but the constructor of a class is not a callable object. So, you can put a factory method inside your class and do like this:

class foo
{
public:
   foo(uint32_t a, uint32_t b, uint32_t c) {};

   static foo* getInstnce(uint32_t a, uint32_t b, uint32_t c)
   {
      return new foo(a,b,c);
   }

};

int main() {
   std::vector<int> args1 = { 1, 2, 3 };

   foo* f = util::unpack_caller(foo::getInstnce, args1);

   return 0;
}
TonySalimi
  • 8,257
  • 4
  • 33
  • 62
  • I want to use template methods for new objects. Because this method is not suitable for my business scenario. – Zephyr Aug 03 '21 at 12:20
  • @JoYous In the working example that you have posted, you are calling `util::unpack_caller(func, args);` and `func` is not a template function. So, if you can be more clear about what you want, maybe the community cab help you more. – TonySalimi Aug 03 '21 at 12:23
  • I hope that friends in the community can modify the unpack_caller function slightly, or add a function similar to std::make_shared(args...) on the original basis, which is more like unpack_caller(args.) ..) so that it can execute the constructor of foo – Zephyr Aug 03 '21 at 12:31
  • @JoYous A site like this is not a site for doing your works. If you want something similar to `make_shared` then why not look at the code of that function to see how it is done. – Phil1970 Aug 03 '21 at 12:38
  • Sorry, because my skills are not enough. I'm really sorry, so I can only seek help from friends. – Zephyr Aug 03 '21 at 12:41