C++ template parameter constraints

Martin Buchholz martin@xemacs.org
Sun Feb 2 18:06:00 GMT 2003


>>>>> "A" == Alexandre Oliva <aoliva@redhat.com> writes:

A> On Jan 30, 2003, Martin Buchholz <martin@xemacs.org> wrote:
>> http://m17n.org/martin/writings/template-parameter-constraints.html

>> (feedback desired)

A> /me thinks the syntax for satisfying might be something like Modula3's
A> `T1 < T2' constraint, used to indicate that type T1 must be the same

As I say elsewhere, I don't like `T1 < T2' because I would like to
express arbitrary compile-time constraints.

A> or derived from T2.  We could use something like:

A> template <class T : predicate<T>::satisfied> declaration;

I don't think the constraint belongs within the <...> template
parameter list, because the constraints apply potentially to ALL the
template parameters, i.e. a template constraint may not be naturally
associated with a particular template parameter.  Standard example is
again `T1 is a subclass of T2'.

A> and then define the predicate template in such a way that satisfied is
A> typedefed to T if T satisfies the predicate, and not defined at all
A> otherwise.

Yes.

A> Another addition that I'd find useful for template meta-programming is
A> an operator such as :?:, similar to :: but with the following
A> additional properties:

A> - its left-hand operand must be a template-dependent type name

A> - if the address of an expression containing :?: is taken and it turns
A>   out that, for a particular instantiation of the template, the member
A>   does not exist, the result is NULL

I would prefer a more general solution.  I imagine a C++ compile-time
function something like

is_compilable<Type, ...> ({ declarations ... ;;; code ... })

You could then ask

is_compilable<T> ({ T x; T y ;;;  x < y;    })
is_compilable<T> ({ T x; T y ;;;  x == y;   })
is_compilable<T> ({ T x;     ;;;  hash (x); })

to decide at compile time whether to use a linked list, a binary tree,
or a hash table to implement a `set<T>' data type, without the user
having to create a special traits class to help out.

A> - a typename expression containing :?: that refers to a type member
A>   that does not exist in a given template name resolves to a new C++
A>   type that, in the absence of a better name, will be called
A>   nosuchtype.

A>   - sizeof applied to nosuchtype is zero

A>   - Any typename expression referencing members of nosuchtype resolve
A>   to nosuchtype

A>   - Any expression involving data members of nosuchtype has type
A>   nosuchtype, and translates to a call of terminate()

A>   - Any expression involving function members of nosuchtype (operator
A>   functions included) succeed overload resolution, but performing the
A>   actual function call evaluates the arguments and calls terminate().

A>   The idea is that such constructs be guarded by NULL- or zero-size
A>   tests and be optimized away, but still parse correctly.

A> Comments?

Compile-time reflection in C++ is incredibly useful, as is shown by
the enormous efforts being applied to implement and use it.  The C++
committee has to recognize that C++ is now a language with a
compile-time MOP, like OpenC++.  But the current MOP is limited and
amazingly kludgy.  A small number of extensions to C++ can probably
fix that.  Finding the appropriate extensions to enable that will be
difficult.

Being able to ask the compiler whether a piece of code is compilable
might be a generalization of your idea above.  Of course, if you
introduce something like is_compilable, people will want to
distinguish among different kinds of compile failures.

Currently, boost's is_base_and_derived causes a compile error if
private inheritance is used.  Implementors of is_base_and_derived
would want to have something like is_compilable, but they might also
want to know WHY something is or is not compilable.



More information about the Gcc mailing list