Home > Enterprise >  Get content from std::variant using element in an integer array
Get content from std::variant using element in an integer array

Time:01-31

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;
}

Can you explain why, and suggest working solution to achieve same purpose?

CodePudding user response:

Since the function get expects either a type or a compile-time constant as an index, your approach will not work.

In order to achieve what you want, you need to modify your function, to make it a function template.

Then, when calling your “validate” function, you can hand in the index value of the bool as a compile-time constant template parameter.

Your program would then look like this:

#include <iostream>
#include <iomanip>
#include <variant>
#include <vector>

using my_type = std::variant<int, float, bool>;
constexpr size_t intPart = 0;
constexpr size_t floatPart = 1;
constexpr size_t boolPart = 2;

template <std::size_t I>
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<I>(input[i]);
    }
    return rst;
}
int main() {
    std::vector<my_type> boolData(4);
    boolData[0].emplace<boolPart>(false);
    boolData[1].emplace<boolPart>(false);
    boolData[2].emplace<boolPart>(true);
    boolData[3].emplace<boolPart>(false);

    bool result = validate<boolPart>(boolData);

    std::cout << "Result = " << std::boolalpha << result << '\n';
}

If you later would need to extend your validate function to handle also the other types of your std::variant, you could do this with variadic templates and constexpr if

Please feedback, if this is solution is sufficient for you.

CodePudding user response:

my_type isn't an array so my_type[i] doesn't make sense.

I'm guessing that std::get<my_type[i]>(input[i]) was meant to be std::get<expected_types[i]>(input[i])? That won't work either as i isn't a compile time constant so can't be used as a template expression.

One workaround would be to unroll your for loop:

#include <vector>
#include <variant>
#include <array>

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

bool validate(std::vector<my_type> input) {
  bool rst = false;
  if (input.size() != 4) {
    return false;
  }
  rst = rst || std::get<expected_types[0]>(input[0]);
  rst = rst || std::get<expected_types[1]>(input[1]);
  rst = rst || std::get<expected_types[2]>(input[2]);
  rst = rst || std::get<expected_types[3]>(input[3]);
  return rst;
}

int main()
{
    unsigned long long i = reinterpret_cast<unsigned long long>(nullptr)    ;
}

If what you're actually trying to do is check that the types match the expected ones then you can just use the index method:

bool validate(std::vector<my_type> input) {
  bool rst = false;
  if (input.size() != 4) {
    return false;
  }
  for (std::size_t i=0; i < 4; i  )
  {
    rst = rst || expected_types[i] == input[i].index();
  }
  return rst;
}
  • Related