Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::get content from std::variant using an element from an integer array as targeted type in std::variant

I have a integer array to retrieve content in std::variant. But it fails compilation, error message No matching function to call 'get'. Can you explain why, and suggest working solution to achieve same purpose?

using my_type = std::variant<int, float, bool>;
constexpr int[] expected_types = {2,2,2,2};
 

bool validate(std::vector<my_type> input) {
  bool rst;
  if (input.size() != 4) {
    return false;
  }
  for (int i = 0; i < 4; i++) {
    rst = rst || std::get<my_type[i]>(input[i]);
  }
  return rst;
}

Here is more context. Class A, B, C both implements the interface bool foo(std::vector<my_type> input). But class A's input is in the format of {int, int, bool}, class B's input is in the format of {int, int, float}, class C's input is in the format of {bool,bool}. expected_types in each class saves its own types in input vector. Then std::get<expected_types[i]> is used to access element in the input vector. Can you suggest an clear and elegant pattern to fit my case?

Many thanks!

like image 385
Biear Avatar asked Aug 28 '26 23:08

Biear


1 Answers

If I understand your validate function correctly, it's supposed to validate that the vector<variant<int, float, bool>> ...

  1. Has the correct length for the type A, B or C.
  2. Contains the variant types indicated by the variant indices inA::expected_types[], B::expected_types[] or C::expected_types[].

It could then take the type it's testing the vector for (A, B or C) as a template parameter and use the variant::index() to check which type the individual variants holds in the vector.

Combine it with a fold over && (since you want all to be true) and you'll get:

template<class T>
bool validate(const std::vector<my_type>& input) {
    if (input.size() != std::size(T::expected_types))  return false;

    return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
        // fold over && :
        return (... && (input[Is].index() == T::expected_types[Is]));
    }(std::make_index_sequence<std::size(T::expected_types)>());
}

If you really want to std::get the expected_types from the vector and use logical OR, that could be done in a similar way, but folding over ||:

template <class T>
bool get_bool(const std::vector<my_type>& input) {
    if (not validate<T>(input)) return false; // use the validation function above

    return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
        // fold over ||
        return (... || (std::get<T::expected_types[Is]>(input[Is])));
    }(std::make_index_sequence<std::size(T::expected_types)>());
}

Demo

like image 51
Ted Lyngmo Avatar answered Aug 31 '26 14:08

Ted Lyngmo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!