0

I have a function that I want to test for each possible input with Catch2. This function has multiple compile-time constants as its parameter. For simplicity, let's say I have two enums

enum class A { a, b};
enum class B { a, b};

and the function

template<A a, B b> void foo() { /* do something */ }

that I want to test with each possible combination of the values of A and B. How can I achieve this in Catch2? I would expect this to be possible without having to list all possible permutations.

What I've tried so far

A a = GENERATE(A::a, A::b);
B b = GENERATE(B::a, B::b);

does not do the trick because I want them to be compile-time constants, i.e., I would need constexpr A a = GENERATE(...) which does not work.

Using TEMPLATE_TEST_CASE_SIG would work:

TEMPLATE_TEST_CASE_SIG("foo works", "[foo]", 
((A T, B V), T, V), (A::a,B::a), (A::b, B::a), (A::a,B::b),(A::b,B::b)) { 
  foo<T, V>();
}

But this would require me to list each possible permutation of A and B, which is not maintainable for any example that is larger than 2*2 values.

Minimal Working Example

https://godbolt.org/z/TzTG7PnW6

Stefan Groth
  • 154
  • 7
  • 1
    Not sure if it is translatable to Catch2, but [create-cartesian-product-expansion-of-two-variadic-non-type-template-parameter](https://stackoverflow.com/questions/46831599/create-cartesian-product-expansion-of-two-variadic-non-type-template-parameter) might interest you. – Jarod42 Jul 29 '21 at 14:42
  • 1
    I added a MWE to my post – Stefan Groth Jul 29 '21 at 14:43

1 Answers1

1

I got it working without the template function and constexpr (which isn't exactly what you wanted), but this should get you a bit closer

#include "catch2/catch_all.hpp"
#include <iostream>

enum class A {
    a, b
};
enum class B {
    a, b
};

// No longer a template function, but serves to print the enumeration
void foo(A a, B b) {
    std::cout << " A: " << static_cast<int>(a) << " B: " << static_cast<int>(b) << std::endl;
}

TEST_CASE("Foo") {
    //constexpr is still refusing to compile here, so i had to remove it. 
    A a = GENERATE(as <A>{}, A::a, A::b);
                // ^ --- This is what gets us our enum to 'generate'
    B b = GENERATE(as <B>{}, B::a, B::b);
    foo(a, b);
}

This generates the output:

 A: 0 B: 0
 A: 0 B: 1
 A: 1 B: 0
 A: 1 B: 1
===============================================================================
test cases: 1 | 1 passed
assertions: - none -

Hope this helps!

Bill Clark
  • 11
  • 2