Finding strings in a matrix Looking for feedback especially regarding design/structure/naming but also anything else that can be improved upon.

Task: Given a (hardcoded) matrix, find out if a given string can be found without visiting a cell twice. 
Movement is restricted to horizontal/vertical and only adjacent cells can be visited.
Print "True" if the input string can be found "False" otherwise.

Matrix:

ABCE
SFCS
ADEE


Example:

Input: CSE

Result: True. (Start from the C in the 2nd row, go right, go up)

Source code:

#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;tuple&gt;
#include &lt;set&gt;

using std::get;
using std::make_tuple;

const std::vector&lt;std::vector&lt;char&gt;&gt; matrix =
{
    {'A', 'B', 'C', 'E'},
    {'S', 'F', 'C', 'S'},
    {'A', 'D', 'E', 'E'},
};

const std::vector&lt;std::tuple&lt;int, int&gt;&gt; directions =
{
    make_tuple(-1, 0),
    make_tuple(0, 1),
    make_tuple(1, 0),
    make_tuple(0, -1),
};

std::set&lt;std::tuple&lt;int, int&gt;&gt; used;
std::string chars;

bool find_next_match(size_t index, std::tuple&lt;int, int&gt; cur_pos)
{
    if (index == chars.size() - 1) return true;

    ++index;

    used.insert(cur_pos);

    for (const auto &amp;dir : directions)
    {
        auto new_pos = make_tuple(get&lt;0&gt;(cur_pos) + get&lt;0&gt;(dir), get&lt;1&gt;(cur_pos) + get&lt;1&gt;(dir));

        if (get&lt;0&gt;(new_pos) &lt; 0 || get&lt;0&gt;(new_pos) &gt; 2) continue;
        if (get&lt;1&gt;(new_pos) &lt; 0 || get&lt;1&gt;(new_pos) &gt; 3) continue;

        if (used.count(new_pos)) continue;

        if (matrix[get&lt;0&gt;(new_pos)][get&lt;1&gt;(new_pos)] != chars[index]) continue;

        if (find_next_match(index, new_pos)) return true;
    }

    used.erase(cur_pos);

    return false;
}

int main (int argc, char **argv)
{
    std::ifstream infile(argv[1], std::ios::in | std::ifstream::binary);

    std::string line;
    while (getline(infile, line))
    {
        chars.clear();
        chars = line;

        bool found = false;
        for (int m = 0; m &lt; 3; ++m)
        {
            for (int n = 0; n &lt; 4; ++n)
            {
                if (matrix[m][n] == chars[0])
                {
                    used.clear();
                    if (find_next_match(0, make_tuple(m, n)))
                    {
                        found = true;
                        break;
                    }
                }
                if (found) break;
            }
        }

        if (found) std::cout &lt;&lt; "True\n";
        else std::cout &lt;&lt; "False\n";
    }
}


Edit 1:

I changed the find_next_match function to operate on the string directly instead of passing an addiontal argument to keep the amount of arguments under 3 (as per recommendation in Robert C. Martins Clean Code)

Revision 2 based on advice by @vnp

Edit 2:

Revision 3 based on advice by @miscco
Avoid magic numbers.

It is not immediately clear what 2 and 3 in find_next_match stand for (same for 3 and 4 in main). Even though the matrix is hardcoded, I recommend to infer its dimensions, rather then hardcode them also.
Avoid globals.

Passing std::string&amp; line as an additional parameter to find_next_match is cleaner then reliance on the global, and obviates the (pretty strange)

    chars.clear();
    chars = line;

tuple vs custom class.

Using a tuple makes the code too verbose to my taste. I'd invest into a struct position with an operator+ overloaded to perform what

    make_tuple(get&lt;0&gt;(cur_pos) + get&lt;0&gt;(dir), get&lt;1&gt;(cur_pos) + get&lt;1&gt;(dir));


does.
Nitpicks.


You should test if infile is opened correctly.
Final print may use a ternary

    std::cout &lt;&lt; (found? "True": "False") &lt;&lt; '\n';

I don't want to start a holy war, but I'd return 0; from main.
Kudos for not using namespace std;