0

I am trying to use catch2 TEMPLATE_TEST_CASE for pairs of types, i.e. instead of templating a single type for each test, I need to use a correlated pair of types. I thought I could use std::variant to store these pairs, but compilation fails with: error: expected primary-expression before ‘)’ token. auto outtype = std::get<0>(TestType);.

I'd appreciate any help for the reason of this error or an alternative solution to this problem. Here is the code snippet:

    using varA = std::variant<OutputA, InputA>;
    using varB = std::variant<OutputB, InputB>;

    TEMPLATE_TEST_CASE("test", "[test][template]", varA, varB) {
    auto outtype = std::get<0>(TestType);
    auto intype  = std::get<1>(TestType);
    }
Armut
  • 969
  • 8
  • 22
  • 3
    Maybe, you confused [std::variant](https://en.cppreference.com/w/cpp/utility/variant) with [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple)? In a `std::variant`, only one type can be active at most. (Imagine `std::variant` as the modern replacement of `union`.) For what you do in your test case, I believe you want to access OutputX _and_ InputX. – Scheff's Cat Mar 16 '21 at 15:43
  • 1
    Btw. regardless whether you use `std::variant` or `std::tuple`, `std::get()` is a function to access a _value_ but you provide a type. Following the example in the doc., `TestType` could be used to make an instance (of the current tested type out of the sequence of types to test), and then you may access that via `std::get()`. Maybe, something like `TestType test; auto outtype = std::get<0>(test); auto intype = std::get<1>(test);` (and the `TestType` still rather a `std::tuple` but not a `std::variant`...) – Scheff's Cat Mar 16 '21 at 15:52
  • 1
    FYI: [The doc.](https://github.com/catchorg/Catch2/blob/devel/docs/test-cases-and-sections.md#type-parametrised-test-cases) I mentioned above. – Scheff's Cat Mar 16 '21 at 15:54

1 Answers1

1

. instead of templating a single type for each test, I need to use a correlated pair of types.

If is only a pair of types, I suppose you can use std::pair; std::tuple, for more types.

I suppose you can try something as

TEMPLATE_TEST_CASE("test", "[test][template]", std::pair<OutputA, InputA>, std::pair<OutputB, InputB>) {
  typename TestType::first_type outvalue = /* some initial value */;
  typename TestType::second_type invalue = /* some initial value */;
}

With std::tuple, to access the single types, you can use std::tuple_element, so

TEMPLATE_TEST_CASE("test", "[test][template]", std::tuple<OutputA, InputA>, std::tuple<OutputB, InputB>) {
  std::tuple_element_t<0u, TestType> outvalue = /* some initial value */;
  std::tuple_element_t<1u, TestType> invalue = /* some initial value */;
}
max66
  • 65,235
  • 10
  • 71
  • 111
  • `std::pair` was what I was looking for. Thank you very much. As a newbie for C++, could you let me know why we need to add `typename`? – Armut Mar 16 '21 at 16:19
  • @Armut - In this particular case, isn't needed; I've corrected the answer. But there are cases where you have to say yo the compiler that whats follows is a type. And I never remember when, exactly, is required. More info in [this page](https://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords) – max66 Mar 16 '21 at 16:27
  • Thank you for the link @max66, I'll try to understand. Indeed for this case, I cannot compile (gcc 9) without adding `typename`. I get a surprisingly clear error: `error: need ‘typename’ before ‘TestType:: first_type’ because ‘TestType’ is a dependent scope`. – Armut Mar 16 '21 at 16:33
  • 1
    @Armut - As I've said, I never remember when, exactly, is requested (in a little test with my compiler, I don't need it... but I don't use catch2 for my test... maybe `TEMPLATE_TEST_CASE` introduce something that impose `typename`). Reintroduced `typename` in the answer. – max66 Mar 16 '21 at 18:48