【问题标题】:std::vector expansion parameters helperstd::vector 扩展参数助手
【发布时间】:2021-08-03 11:31:18
【问题描述】:

这段代码不是我写的,希望大家帮帮我。

我有如下代码,可以合理扩展普通函数的参数。

我希望它可以,扩展,类的构造函数。

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

例如通过以模板的形式添加一个类函数,并自动寻找构造函数的参数。

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

【问题讨论】:

  • 构造函数没有返回类型。此外,您 cannot take a constructor's address 也没有办法让您指向构造函数以从其他地方调用它。所以,不,这是不可能的,除非你创建一个虚拟的辅助函数来做与构造函数相同的事情并使用它。
  • 执行构造函数的目的不是返回类型。但是对于新对象,返回新对象的指针地址。就像 rttr 反射库一样。

标签: c++


【解决方案1】:

unpack_caller 方法的第一个参数应该是可调用对象,但类的构造函数不是可调用对象。所以,你可以在你的类中放置一个工厂方法,然后这样做:

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

【讨论】:

  • 我想对新对象使用模板方法。因为这种方式不适合我的业务场景。
  • @JoYous 在您发布的工作示例中,您正在调用util::unpack_caller(func, args);func 不是模板函数。所以,如果你能更清楚自己想要什么,也许社区出租车能帮到你更多。
  • 希望社区的朋友可以稍微修改一下unpack_caller函数,或者在原来的基础上增加一个类似std::make_shared(args...)的函数,更像unpack_caller(args.) ..) 以便执行 foo 的构造函数
  • @JoYous 这样的网站不适合做你的工作。如果您想要类似于make_shared 的东西,那么为什么不查看该函数的代码以了解它是如何完成的。
  • 对不起,我的技术不够。实在抱歉,只能求助朋友了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多