Deduce成员函数参数/返回类型

时间:2017-02-15 10:45:22

标签: c++ metaprogramming

我有以下代码:

template <class... Args>
struct TypeList
{
    static constexpr size_t size = sizeof...(Args);

    template <std::size_t N>
    using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
};

struct Generator
{
    std::tuple<float, float> process(float, int, size_t)
    {
        return std::make_tuple(0.0f, 1.0f);
    }
};

是否有任何方法可以推导出元组模板参数以及Generator::process的输入参数,以便构造具有以下模板参数的类。

struct Node<GenType, ReturnTypesList, ArgumentTypeList>

其中ReturnTypesList包含返回元组的模板参数,ArgumentTypeList包含过程函数的可变参数类型。假设所有过程函数都将返回一个元组。

2 个答案:

答案 0 :(得分:0)

我没有得到你想要的东西,但可能这样的东西对你有用:

#include <type_traits>
#include <tuple>

template <class... Args>
struct TypeList
{
    static constexpr size_t size = sizeof...(Args);

    template <std::size_t N>
    using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
};

struct Generator
{
    std::tuple<float, float> process(float, int, size_t)
    {
        return std::make_tuple(0.0f, 1.0f);
    }
};

template<typename GenType, typename ReturnTypesList, typename ArgumentTypeList>
struct Node {};

template<typename T>
struct S
{
    template<typename... RArgs, typename... Args>
    static auto gen(std::tuple<RArgs...>(T::*)(Args...)) -> Node<T, TypeList<RArgs...>, TypeList<Args...>>;
};

template<typename T>
using NodeType = decltype(S<T>::gen(&T::process));

int main()
{
    static_assert(std::is_same<NodeType<Generator>,  Node<Generator, TypeList<float, float>, TypeList<float, int, size_t>>>::value, "!");
}

NodeType是专门针对特定生成器的必需类型,您可以从main中的测试中看到。
在具体案例中:

Node<Generator, TypeList<float, float>, TypeList<float, int, size_t>>

不介意成员是作为函数参数而不是模板参数提供的。无论如何,整个过程在编译时已解决

作为旁注,该解决方案不适用于那些过载process的生成器。

答案 1 :(得分:-1)

#include <tuple>

template <class...>
struct Node;

struct Generator {
  std::tuple<float, float> process(float, int, size_t);
};

template <class... Args1, class ClassType, class... Args2>
auto foo(std::tuple<Args1...> (ClassType::*)(Args2...)) -> Node<ClassType, Args1..., Args2...>;



int main() {

  // T is Node<Generator, float, float, float, int, size_t>
  using T = decltype(foo(&Generator::process));

  return 0;
}
正确推导出

Args1Args2,因为将推断出模板参数列表最后出现的包扩展。传递给foo的成员函数指针包含所有必需的类型。 foo的所有模板参数将单独推导,然后在特定调整后合并为与&Generator::process类型匹配的类型。 Link

不相关:如果流程尚未返回std::tuple,我们仍然可以使用模板模板参数,即template <class...> class TT

根据@Martin Bonner

提供的信息进行编辑
template <class...>
struct Node {};

template <class...>
struct TypeList {};

struct Generator {
  std::tuple<float, float> process(float, int, size_t) {}
};

template <class... ReturnArgs, class GeneratorType, class... Args>
auto magic(std::tuple<ReturnArgs...> (GeneratorType::*arg)(Args...))
    -> Node<GeneratorType, TypeList<ReturnArgs...>, TypeList<Args...> > {
  using ReturnType =
      Node<GeneratorType, TypeList<ReturnArgs...>, TypeList<Args...> >;

  return ReturnType{};
}

int main() {
  magic(&Generator::process);

  return 0;
}