I'm trying to work out a design for dynamically determining file types, and
for generating new files of a given type. I'm curious to know what others
think of my current strategy. Is it "so einfach wie möglich machen, aber
nicht einfacher" or "Rube Goldberg"?
The first part of this has to do with a technique used in the C++ Standard
Library, so I suspect the purist will not have any objection. It's the
approach used to build the inheritance hierarchy for iterators. Understand
"Role" to mean what role a file has such as header, source, etc. I have
organized my types as follows:
namespace files {
struct FileRole {};
struct CppRole : FileRole{};
struct CppSrcRole : CppRole {};
struct CppHeaderRole: CppRole {};
// create a functor class that takes some kind of descriptive
// statement about a file, and returns role information in the
// form of a subclass of FileRole.
struct RoleRecognizer {
virtual FileRole* operator(const QFileInfo& fileInfo) const = 0;
};
// There is a problem, however. There are no virtual functions in
// any of the types derived from FileRole. The type information is,
// therefore only useful at compiletime. So I do this:
struct FileRole {virtual ~FileRole (){}};
struct CppRole : FileRole{virtual ~CppRole (){}};
struct CppSrcRole : CppRole {virtual ~CppSrcRole (){}};
struct CppHeaderRole: CppRole {virtual ~CppHeaderRole(){}};
}
I can now sniff the return value from RoleRecognizer::operator(fileInfo); to
determin, at runtime, what kind of file I have. A much simpler approach
would be to use an enum such as
enum Role {
FileRole,
CppRole,
CppSrcRole,
CppHeaderRole
};
And then return values of type Role.
There are problems with this approach. For one, I have never like the open
nature of enums. I can check that the value I pass is declared to be of a
given enum type, but I cannot ensure the value is one of those declared in
the enum definition. Enums are therefore, to some extent nondeterministic.
One great advantage to using enums is that they require very little simple
to declare. There is a disadvantage that comes with that simplicity. I
cannot later add functionality to an enum value such as a conversion
operator to std::string.
IIRC, Stroustrup cautions against using RTTI for flow control. There are
places, such as in 3D graphics, where I have seen RTTI used to great
advantage. I intend to use RTTI for flow control when determining what
kind of object to create for an in-memory representation of a file. The
idea is to subclass RoleRecognizer to implement specific strategies for
resolving file roles. For example *.cpp vs *.cc, or extensionless
filesnames with file type meta information on the first line. Such as:
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 Robert Osfield
Is this a path others have headed down, and found problematic?
--
NOUN:1. Money or property bequeathed to another by will. 2. Something handed
down from an ancestor or a predecessor or from the past: a legacy of
religious freedom. ETYMOLOGY: MidE legacie, office of a deputy, from OF,
from ML legatia, from L legare, to depute, bequeath. www.bartleby.com/61/