Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Difference in supplying two variant objects separately vs in an array

I have two variant objects of the following type

struct FigureMove {};
struct PieceMove {};
using Move = std::variant<FigureMove, PieceMove>;

I want to supply two Move objects to a function and call different functions depending on the underlying types in the variants.
I have two different versions of the function which takes the Move objects. One taking them as separate function arguments and one taking both of them in an array.
Note, I plan on supplying always one FigureMove and one PieceMove, just their order is not clear beforehand.

bool areMovesValid(const FigureMove &figureMove0, const PieceMove &pieceMove1)
{
    return {};
}

bool areMovesValid(const PieceMove &pieceMove0, const FigureMove &figureMove1)
{
    return {};
}

//#define USE_ARRAY

#ifdef USE_ARRAY
bool areMovesValid(const std::array<Move, 2> &moves)
{
    const auto &variantMove0 = moves[0];
    const auto &variantMove1 = moves[1];

#else
bool areMovesValid(const Move &variantMove0, const Move &variantMove1)
{
#endif
    return std::visit(
        [variantMove1](const auto move0)
        {
            return std::visit(
                [move0](const auto move1)
                {
                    return areMovesValid(move0, move1);
                },
                variantMove1);
        },
        variantMove0);
}

The version taking the array throws tons of compile time errors. Using gcc or clang.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Why is that and how can I fix it?

Here is the code on godbolt.

>Solution :

return areMovesValid(move0, move1);

When not using an array parameter this results in infinite recursion for a combination of two values that are the same type, because overload resolution will pick the same areMovesValid.

When using an array parameter version: overload resolution fails, since these two parameters cannot be converted to a single std::array, and the remaining overloads don’t match.

If you choose to name the third function, the one that takes a pair of Moves as something other than areMovesValid, neither version will compile.

I plan on supplying always one FigureMove and one PieceMove

That’s nice, but your C++ compiler is not taking your word for it. The combination of the two std::visit calls will also generate the code paths where both parameters are both FigureMoves and PieceMoves. And that has to compile, somehow.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading