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