Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Problem

I was just trying to debug a set of file-manipulation routines I wrote for a program I am working on. One of them kept returning an INVALID_HANDLE error.

Explanation

I figured out what the problem was. It turns out that because I provided several overloads so that I could call the function with either a file handle or filename, I ended up creating ambiguous overloads.

For example (not variadic functions; the ellipses are just for simplification purposes):

INT CopyFileSection ( HANDLE fIn, HANDLE fOut, … );
INT CopyFileSection ( HANDLE fIn, TCHAR* fOut, … );
INT CopyFileSection ( TCHAR* fIn, HANDLE fOut, … );
INT CopyFileSection ( TCHAR* fIn, TCHAR* fOut, … );

The first one (HANDLE, HANDLE) does the main work while the others just open the file pointed to by the filename and call the first function.

The problem is that a HANDLE is just a pointer, so the compile can’t figure out which one I am calling (even though to me it was obvious), and ends up calling HANDLE, HANDLE even when I pass a pointer to a string, so naturally it fails since the pointer is not a file handle.

Question

I want to provide maximum flexibility, so short of re-writing to use std::string instead of TCHAR* for the filenames (which I actually did include as well), what suggestions are there to deal with this sort of scenario?


Related

As a related side note—a separate question?—I was wondering about the ease, safety, and feasibility of providing overloads for all (or at least a set of) possible permutations.

For example, with a function that takes two files, you could use HANDLE, TCHAR*, and string (probably others, but in this case we’ll stick with these three). This means there are up to nine overloads just for the files: HH, HT, HS, TH, TT, TS, SH, ST, SS. Let alone if there are other arguments that could provide more overloads. Surely there must be a better way to both provide flexibility in calling the function and clean, understandable, and maintainable code.

share|improve this question

1 Answer 1

The easiest way to limit the combinatorial explosion of your overloads is to introduce a small helper class that can accept all the various types and convert them to a single common type.

For example

class FileHelper {
public:
    FileHelper(HANDLE& h) : handle(h) {}
    FileHelper(const TCHAR* fName) : handle(openFile(fName) {}
    FileHelper(const std::string& fName) : handle(openFile(fName) {}

    HANDLE getHandle() const { return handle; }
private:
    HANDLE handle;
}

INT CopyFileSection ( FileHelper fIn, FileHelper fOut, … );

There is only one overload of CopyFileSection and that overload takes two FileHelper instances as stand-ins for a pair of file handles. The FileHelper class takes care of accepting the different possibilities (existing handle, file name, etc.) and obtaining a file handle for each of them.

Note that the first FileHelper constructor takes a non-const HANDLE reference. This was done deliberately to inhibit conversions from types that could be converted implicitly to a HANDLE, such as (other) pointer types. This has the side-effect that you also can't pass directly handles that were returned by a function, but they need to be stored in a variable first.

share|improve this answer
    
Interesting idea. Your helper class idea sounds like it could indeed help mitigate the permutation issue, and thanks for mentioning implicit conversions; that might be the key to the immediate problem. I’ll give it a shot on Monday. –  Synetech Jul 13 '13 at 16:54
    
Implicit conversions is, with almost 100% certainty your immediate problem –  Ptolemy Sep 11 '13 at 8:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.