deduce function parameter types of overloaded member function by argument count

125 views Asked by At

Currently I'm looking for some way to get the parameter types of an overloaded member function by argument count and instance type. In my case we know the name, the return type (void) and the argument count. In addition there can't be a second overload with the same argument count and the functions are never cv nor ref qualified.

A sample:


#include <tuple>
#include <type_traits>
#include <iostream>

class TupleLikeType{
public:
    void Deconstruct(int& a, char& b){
      a = 12;
      b = 'A';
    }
    void Deconstruct(int& a, char& b, bool& c){
      Deconstruct(a, b);
      c = true;
    }
};

template<typename Type, std::size_t ArgCount>
class TupleDeconstructTypes{
public:
    using type = 
    //to implement
    std::conditional_t<ArgCount == 2, 
        std::tuple<int&, char&>, std::tuple<int&, char&, bool&>
    >
    //to implement end
    ;
};

template<typename T>
    class DeconstructAdapter
    {
    private:
        T& obj;
    public:
        template<
            typename DepT = T
            , typename... Args
        >
        constexpr void operator()(Args&&... args)
        {
            return obj.Deconstruct(std::forward<Args>(args)...);
        }
    public:
        constexpr DeconstructAdapter(T& toDeconstruct) : obj(toDeconstruct)
        {
        }
    };

template<typename Tuple>
class TupleWithOutRefs{};
template<template <typename...> typename Tuple, typename... T>
class TupleWithOutRefs<Tuple<T...>>{
public:
    using type = Tuple<std::remove_reference_t<T>...>;
};

template<
  std::size_t ArgCount
  ,typename T
  ,typename Args = typename TupleDeconstructTypes<T, ArgCount>::type
  ,typename TempTuple = typename TupleWithOutRefs<Args>::type

> 
auto CreateTuple(T& t){

    auto adapter = DeconstructAdapter(t);
    TempTuple result{};

    //std::apply calls std::invoke
    //during this call all out-references are bound to our allocated stack memory
    std::apply(adapter, result);

    return result;
}


int main(){
    //usage
    static_assert(std::is_same_v<
        TupleDeconstructTypes<TupleLikeType, 2>::type,
        std::tuple<int&, char&>
    >);

    TupleLikeType t;
    auto tuple = CreateTuple<2>(t);
    std::cout << std::get<0>(tuple);
}

Do you have any idea to solve this in a generic way?

1

There are 1 answers

2
Jarod42 On BEST ANSWER

With limited number, you can do something like:

template <std::size_t Size>
struct helper;

template <>
struct helper<0>
{
    template <typename C>
    std::tuple<> operator() (void (C::*) ()) const;
};

template <>
struct helper<1>
{
    template <typename C, typename T1>
    std::tuple<T1> operator() (void (C::*) (T1)) const;
};

template <>
struct helper<2>
{
    template <typename C, typename T1, typename T2>
    std::tuple<T1, T2> operator() (void (C::*) (T1, T2)) const;
};

template <>
struct helper<3>
{
    template <typename C, typename T1, typename T2, typename T3>
    std::tuple<T1, T2, T3> operator() (void (C::*) (T1, T2, T3)) const;
};

// ...

template<typename Type, std::size_t ArgCount>
using TupleDeconstructTypes = decltype(helper<ArgCount>{}(&Type::Deconstruct));

Demo