Boost.Interfaces

Disclaimer

Not a Boost library

Overview

Definition

Boost.Interfaces provides a macro-based Interface Definition Language (IDL) which can be used to define C++ class types called interfaces. An interface is a lightweight value type associated with a set of named function signatures. An interface instance can be bound at runtime to any object which implements the interface, i.e., to any object of a type with accessible non-static member functions having the same name and signature as the set of functions associated with the interface. The functions of the bound object can then be invoked through the interface instance using the “dot” operator. Binding is completely non-intrusive: the object's type need not declare any virtual functions or derive from any particluar base class.

Interfaces were described in a September 2004 C/C++ Users Journal article by Christopher Diggins ([Diggins2])

Conventions

Applications

Current applications of Boost.Interfaces include:

Planned future applications include:

Possible future applications include:

See Future Directions.

Examples

The following interface defintion uses pseudocode instead of the macro-based IDL.

interface IAnimal {
    void speak();
};

Given this definition, we can define a class which implements IAnimal as follows:

class Dog {
    void speak() { std::cout << "Wooof\n"; }
};

We can construct an instance of IAnimal bound to an instance of Dog and invoke the Dog's member function speak() as follows:

int main()
{
    Dog d;
    IAnimal a = d;
    a.speak(); // Prints "wooof"
}

We could also define an empty instance of IAnmial and then bind it to an instance of Dog:

int main()
{
    Dog d;
    IAnimal a;
    a = d;
    a.speak(); // Prints "wooof"
}

After binding an object to an interface instance, we can retrieve the object using the function template extract:

int main()
{
    Dog d;
    IAnimal a = d;
    Dog& d2 = extract<Dog>(a);
}

An extraction will succeed only if the static type of the object, at the point it was bound to the interface instance, is the same as or derived from the target type; otherwise, extract will throw an exception of type bad_extract.

Next, we can cause the interface instance to become unbound from the object by assigning 0 to it:

int main()
{
    Dog d;
    IAnimal a = d;
    a.speak(); // Prints "wooof"
    a = 0;    
    a.speak(); // Undefined behavior: a is empty
}

See Future Directions: Qualifiers for a description of a checked interface type which would throw an exception in the above example.

Interface instances may also be passed to and returned from functions:

IAnimal source()
{
    static Dog d;
    return IAnimal(d);
}

void sink(IAnimal a)
{
    a.speak();
}

int main()
{   
    IAnimal a = source();
    a.speak(); // Prints "wooof"
    Dog d;
    sink(d);   // Prints "wooof"
}

Finally, interface instances do not manage the lifetimes of their bound objects:


int main()
{   
    IAnimal outer; 
    {
        Dog d;
        outer = d;
    }
    outer.speak(); // Undefined behavior

}

To manage the lifetime of the bound object, use a Smart Interface Pointer or Smart Reference.

Known Issues

There are several problems with the current implementation:

Dependencies

The core implementation of Boost.Interfaces depends on

The implementation of the templates shared_ptr and shared_obj uses depends on the Boost Smart Pointers library; see [Colvin].

Acknowledgments

If I forgot to mention you, please let me know!

Contact


Sha'arei Tefila, an Orthodox Shul (Synagogue) in Salt Lake City, Utah Chabad Lubavitch of Utah