Library: Literal now default constructible to empty string

The class Literal is used as a thin wrapper to mark the fact that
some string parameter or value is assumed to be given *literally*

For the contract this indicates
- that storage is somewhere
- storage is not owned and managed by Literal
- yet storage guaranteed to exist during the whole lifetime of the program
- Literal can not be altered
- Literal is transparently convertible to const char *


Currently I am in the course of building some path abstraction, and for that
task it makes sense to hold an array of Literals (instead of pointers), just
because it expresses the intent way more clear. I do not see anything in the
above mentioned contract to prohibit a default constructed Literal, with the
empty string being the most obvious choice.

Note: there is the class Symbol, which derives from Literal. Symbol takes
arbitrary strings, but *interns* them into a static symbol table.
This commit is contained in:
Fischlurch 2017-09-30 17:45:38 +02:00
parent 1138898989
commit dd45d6110d
2 changed files with 40 additions and 14 deletions

View file

@ -25,8 +25,8 @@
** The implementation of the lib::Symbol token relies on unique string pointers,
** such as to create one distinct identity for each distinct "symbol string". The idea
** is to generate unique and distinct numeric token IDs, while still holding onto a human readable
** string. Which in turn requires us to manage a registry of already known symbol strings; when
** a Symbol object with such an already known string is created, it will thus connect internally
** string. Which in turn requires us to manage a registry of already known symbol strings; when a
** Symbol object with such an already known string is created, it will thus connect internally
** to the known token ID.
**
** @todo as of this writing (4/2017), it is neither clear if we really need such a facility, nor

View file

@ -21,16 +21,30 @@
*/
/** @file symbol.hpp
** WIP placeholder definition for a planned Symbol datatype.
** Marker types to indicate a literal string and a Symbol.
** Instead of working just with pointers, which could represent pretty much anything,
** it is prudent to express the meaning at interfaces and for variables and members explicitly.
**
** @todo for the (currently just planned as of 11/08) rules based configuration
** in the Proc-Layer a explicit Symbol datatype will probably very helpful.
** For now just a typedef is sufficient. A real Symbol datatype should
** - be definable by string constant
** - integrate smoothly with std::string
** - provide a unique numeric index for each distinct Symbol
** - automatically maintain a symbol table at runtime to support this
** - provide some magic (macros) allowing to build distinct types based on symbols.
** On concept level, while a string is just some sequence of characters and nothing can be said
** about mutability or lifetime, a Literal on the contrary is meant to be _static._ It is fixed
** and assumed to exist literally as is during the whole lifetime of the execution. The concept
** of a Symbol is related, yet slightly different: it is meant to be a distinguishable fixed,
** unique token. _Identical sequence_ of characters means we have exactly the _same Symbol._
**
** These concepts can be fused by treating Symbol as a specialisation of Literal, additionally
** maintaining an automatically populated, static [symbol table](\ref symbol-table.hpp), and
** we close the circle by allowing Symbol instances to be created from strings at runtime.
**
** @remark this started on occasion 11/2008, just with a typedef to mark assumption on interfaces
** for rules based configuration in the Proc-Layer. Over time, conversions, comparison and
** hashcode implementation were added. It turned out that the most smooth integration in
** coding practice is achieved when allowing transparent conversion for Literal, but not
** for Symbol or std::string.
** @todo 9/2017 consider this mostly as settled, but might require some finishing touches
** - maybe improve interoperation of Symbol and std::string
** - investigate performance of the automatic symbol table
** - improve Lifecycle in startup and shutdown phase
** - maybe some metaprogramming magic to build distinct types based on symbols.
**
** @see symbol-impl.cpp
** @see configrules.hpp
@ -50,13 +64,21 @@
namespace lib {
/** inline string literal
* This is a marker type to handle literally given C-Strings.
* This is a _marker type_ to indicate that
* - the string was given literally
* - storage is _somewhere_, not managed by Literal,
* yet guaranteed to exist during the whole lifetime
* - it is transparently convertible to/from C-string
* - defaults to the empty string
* - can not be altered
*/
class Literal
{
const char * str_;
public:
Literal(); ///< empty string by default
Literal (const char* literal)
: str_(literal)
{ }
@ -77,7 +99,7 @@ namespace lib {
bool operator== (const char* cString) const;
protected:
/** Assignment prohibited */
/** Assignment generally prohibited */
Literal& operator= (const char* newStr)
{
str_ = newStr;
@ -86,7 +108,8 @@ namespace lib {
};
/** Token or Atom with distinct identity
/** Token or Atom with distinct identity.
* It can be created from arbitrary strings, yet not altered
* @note same literal string==same pointer representation
*/
class Symbol
@ -138,6 +161,9 @@ namespace lib {
* with raw char ptrs (typically literal values) */
extern const size_t STRING_MAX_RELEVANT;
/** @note storage guaranteed to exist */
inline Literal::Literal() : str_(Symbol::EMPTY) { }
/* ===== to be picked up by ADL ===== */