1

There are working answers here that are able to count the number of arguments functions take: Get function parameters count

Using one of these I can find that this takes 5 arguments:

void foo(const std::string&, const std::string&, const std::string&, const std::string&, const std::string&) {}

However I would like to get counting to work for this:

struct Foo {
    void foo(const std::string&, const std::string&, const std::string&, const std::string&, const std::string&) {}
};

In the code below the first std::cout says 5 and the second one is a compiler error if it is uncommented:

#include <iostream>
#include <string>

struct Foo {
    void foo(const std::string&, const std::string&, const std::string&, const std::string&, const std::string&) {}
};

void foo(const std::string&, const std::string&, const std::string&, const std::string&, const std::string&) {}

template <class R, class... ARGS>
struct function_ripper {
    static constexpr size_t n_args = sizeof...(ARGS);
};

template <class R, class... ARGS>
auto constexpr make_ripper(R (ARGS...) ) {
    return function_ripper<R, ARGS...>();
}

int main() {
    std::cout << decltype(make_ripper(foo))::n_args << std::endl; // 5
    //std::cout << decltype(make_ripper(Foo::foo))::n_args << std::endl; // error
    return 0;
}

This is the error:

foo.cpp: In function ‘int main()’:
foo.cpp:22:44: error: invalid use of non-static member function ‘void Foo::foo(const string&, const string&, const string&, const string&, const string&)’
     std::cout << decltype(make_ripper(Foo::foo))::n_args << std::endl;
                                            ^~~
foo.cpp:22:44: error: invalid use of non-static member function ‘void Foo::foo(const string&, const string&, const string&, const string&, const string&)’
foo.cpp:22:18: error: decltype evaluates to ‘<type error>’, which is not a class or enumeration type
     std::cout << decltype(make_ripper(Foo::foo))::n_args << std::endl;

How can this be done?

asimes
  • 5,749
  • 5
  • 39
  • 76

1 Answers1

3

You might add another make_ripper function template to handle member functions:

template <class C, class R, class... ARGS>
auto constexpr make_ripper(R (C::*)(ARGS...) ) {
    return function_ripper<R, ARGS...>();
}

Then call it like:

decltype(make_ripper(&Foo::foo))::n_args

EXAMPLE

Edgar Rokjān
  • 17,245
  • 4
  • 40
  • 67
  • And probably one for const member functions too. There are other cv-ref-quailifed combinations possible, but const and non-const are by far the most common – SirGuy Jan 18 '18 at 21:51