2.4 Overview (version 2)
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • A C++ interface to SWI-Prolog
        • A C++ interface to SWI-Prolog (Version 2)
          • Overview (version 2)
            • Design philosophy of the classes
            • Summary of classes
            • Naming conventions, utility functions and methods (version 2)

2.4.1 Design philosophy of the classes

See also section 2.4.3.

The general philosophy for C++ classes is that a "half-created" object should not be possible - that is, the constructor should either succeed with a completely usable object or it should throw an exception. This API tries to follow that philosophy, but there are some important exceptions and caveats. (For more on how the C++ and Prolog exceptions interrelate, see section 2.16.)

The various classes (PlAtom, PlTerm, etc.) are thin wrappers around the C interface's types (atom_t, term_t, etc.). As such they inherit the concept of "null" from these types (which is abstracted as PlAtom::null, PlTerm::null, etc., which typically is equivalent to 0). You can check whether the object is "fully created" by using the verify() method - it will throw an exception if the object is null.

However, most of the classes have constructors that create a "complete" object. For example,

PlAtom foo("foo");

will ensure that the object foo is useable and will throw an exception if the atom can't be created.

To help avoid programming errors, most of the classes do not have a default "empty" constructor. For example, if you with to create a PlAtom that is uninitialized, you must explicitly use PlAtom(PlAtom::null). This make some code a bit more cumbersome because you can't omit the default constructors in struct initalizers.

Many of the classes wrap long-lived items, such as atoms, functors, predicates, or modules. For these, it's often a good idea to define them as static variables that get created at load time, so that a lookup for each use isn't needed (atoms are unique, so PlAtom("foo") requires a lookup for an atom foo and creates one if it isn't found). Sometimes, it's desirable to create them "lazily", such as:

static PlAtom foo(PlAtom::null};
   ...
if ( foo.is_null() )
  foo = PlAtom("foo");

The class PlTerm (which wraps term_t) is the most used. Although a PlTerm object can be created from a term_t value, it is intended to be used with a constructor that gives it an initial value. The default constructor calls PL_new_term_ref() and throws an exception if this fails. The various constructors are described in section 2.9.1. Note that the default constructor is not public; to create a "variable" term, you should use the subclass constructor PlTerm_var().