Home > OS >  C Passing a template function to another function without specifying the template parameter
C Passing a template function to another function without specifying the template parameter

Time:08-14

Intro

Two weeks ago I started a new project and came along another idea for a project: a test runner for automating tests of template functions - which I'm currently working on. The main reason behind all that is that I want to

  1. learn more about (modern) C and
  2. implement some stuff from my uni lectures.

Said test runner should be able to test a template function, i.e.:

// Said template function (*)
template <class T>
T add(T a, T b) {
  return a   b;
}

Setup Explanation

In order to do so I created a class TestRunner (shown in the following) that gets a tuple of parameters via its constructor and has a friend (run(...)) that executed the test.

template <class... PS>
  class TestRunner {
  public:
    // constructors
    explicit TestRunner(std::tuple<PS...> paramSetTuple) : paramSets_(paramSetTuple) {}

    // ... other unimportant stuff ...
    
    // friends
    template <size_t idx, typename F, class... P>
    friend constexpr void run(TestRunner<P...> testRunner, F&& testFunc, std::string_view testFuncName);

  private:
    std::tuple<PS...> paramSets_;
  };

As seen here run(...) gets the an instance of TestRunner, a rvalue reference to the function that shall be tested and some string for a better console output.

(just FYI, but not important to the problem itself: The reason for making this friend function is that I want to implement different tests and I don't want to just copy paste the basic functionality behind run(...) as well as I want to created a macro that spares me of the run(...)'s last argument.)

Finally, the problem itself:

I want to be able to pass add(...) to run(...) without specifying add(...)'s template parameter, because this template parameter should be specified automatically when I use the add(...) function in run(...), which looks like this:

template <size_t idx = 0, typename F, ParameterSetConcept... P>
  constexpr void run(TestRunner<P...> testRunner, F&& testFunc, std::string_view testFuncName) {
      // ... some stuff to iterate through the tuple ...
      
      // ... some other stuff to get the input parameters for add(...) and it's expected output
      //     for now, let's just say the input is a tuple i.e. testInputs,
      //     and the expected output i.e. expectedOutput

      auto output = std::apply(std::forward<F>(testFunc), testInputs;
      if ( output == expectedOutput ) { 
        // this == is just an example for a successful test 
        // (more options will be implemented later)

        run<idx   1>(testRunner, std::forward<F>(testFunc), testFuncName);
      } else {
        // ... some error output ... 
      }
  }

It be said that the iteration through tuples, and fetching of the tuple testInputs as well as the expected output expextedOutput work just fine.

Now what I need is to be able to call run(...) in the main (or a gtest) without specifying it's template parameter. This may look something like this:

int main() {

  TestRunner testRunner(...); // init testRunner as it's supposed to be
  run(testRunner, add, "add");

  return 0;
}

Is there even a solution to this problem? In advance: THANKS FOR ANY HELP!

Last Comments

I'm aware that the total setup of using such a 'complex' construct in a UnitTest as I mentioned before (gtest) might be a bad idea for the UnitTest concept itself, but I mainly do all this because I want to learn something about C and came along this problem. Please don't judge ^^ I know that there is a option for value parameterized tests and even type parameterized tests in the gtest framework.

CodePudding user response:

The closest thing I can think of is,

auto call_add = [](auto&&... args){ return add(std::forward<decltype(args)>(args)...); };
doSomethingWithAdd(call_add);

Of course, you can add a macro for it if it's too complicated.

  • Related