Topic: Addition of template "specifications" to prevent STL missing member/type mismatch spam errors


Author: "illumanus@yahoo.com" <illumanus@yahoo.com>
Date: Thu, 19 May 2005 15:31:52 CST
Raw View
I have often run into cases when using template classes and functions
that there is a "specification" for types that are allowed to be passed
to the template. The "specification" is assumed to be understood by the
programmer and if any deviations happen, then member missing, type
mismatch errors and "instantiated from" spam result. This is
complicated by the very lengthy type declarations for some standard STL
classes and the fact that the error report will be sourced to the
template function or class source code and NOT the code where the error
really is. It is quite cumbersome to diagnose exactly where the
deviation from the "specification" occurred. Here is a simplified
example of passing a type to a template that has an assumed
"specification":

#include <algorithm>

template<class T>
struct MyBiIterator : public std::iterator<
std::bidirectional_iterator_tag, T> {
  typedef MyBiIterator this_t;
  this_t &operator ++();
  this_t &operator ++(int);
  size_t &operator --(); // Whooops typo
  this_t &operator --(int);
  T &operator *() const;
  T *operator ->() const;

  // Whoops forgot to declare
  // bool operator !=(const this_t &) const;
};

int main()
{
 std::copy_backward(MyBiIterator<int>(), MyBiIterator<int>(),
MyBiIterator<int>());
};

When compiled with GCC, this results in two pages of difficult to
decipher errors. The errors appear to come from the STL library code
itself, when the problem is really in the above code.
GCC3.4.3 output:
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h: In function `_BidirectionalIterator2
std::__copy_backward(_Bidirectio
nalIterator1, _BidirectionalIterator1, _BidirectionalIterator2,
std::bidirection
al_iterator_tag) [with _BidirectionalIterator1 = MyBiIterator<int>,
_Bidirection
alIterator2 = MyBiIterator<int>]':
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:396:   instantiated from `static _BidirectionalIterator2
std::__copy_b
ackward_dispatch<_BidirectionalIterator1, _BidirectionalIterator2,
_BoolType>::c
opy(_BidirectionalIterator1, _BidirectionalIterator1,
_BidirectionalIterator2) [
with _BidirectionalIterator1 = MyBiIterator<int>,
_BidirectionalIterator2 = MyBi
Iterator<int>, _BoolType = __true_type]'
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:429:   instantiated from `_BI2 std::__copy_backward_aux(_BI1,
_BI1, _B
I2) [with _BI1 = MyBiIterator<int>, _BI2 = MyBiIterator<int>]'
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:445:   instantiated from `_BI2
std::__copy_backward_output_normal_iter
ator(_BI1, _BI1, _BI2, __false_type) [with _BI1 = MyBiIterator<int>,
_BI2 = MyBi
Iterator<int>]'
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:464:   instantiated from `_BI2
std::__copy_backward_input_normal_itera
tor(_BI1, _BI1, _BI2, __false_type) [with _BI1 = MyBiIterator<int>,
_BI2 = MyBiI
terator<int>]'
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:498:   instantiated from `_BI2 std::copy_backward(_BI1, _BI1,
_BI2) [w
ith _BI1 = MyBiIterator<int>, _BI2 = MyBiIterator<int>]'
crap.cpp:17:   instantiated from here
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:369: error: invalid type argument of `unary *'
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:396:   instantiated from `static _BidirectionalIterator2
std::__copy_b
ackward_dispatch<_BidirectionalIterator1, _BidirectionalIterator2,
_BoolType>::c
opy(_BidirectionalIterator1, _BidirectionalIterator1,
_BidirectionalIterator2) [
with _BidirectionalIterator1 = MyBiIterator<int>,
_BidirectionalIterator2 = MyBi
Iterator<int>, _BoolType = __true_type]'
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:429:   instantiated from `_BI2 std::__copy_backward_aux(_BI1,
_BI1, _B
I2) [with _BI1 = MyBiIterator<int>, _BI2 = MyBiIterator<int>]'
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:445:   instantiated from `_BI2
std::__copy_backward_output_normal_iter
ator(_BI1, _BI1, _BI2, __false_type) [with _BI1 = MyBiIterator<int>,
_BI2 = MyBi
Iterator<int>]'
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:464:   instantiated from `_BI2
std::__copy_backward_input_normal_itera
tor(_BI1, _BI1, _BI2, __false_type) [with _BI1 = MyBiIterator<int>,
_BI2 = MyBiI
terator<int>]'
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:498:   instantiated from `_BI2 std::copy_backward(_BI1, _BI1,
_BI2) [w
ith _BI1 = MyBiIterator<int>, _BI2 = MyBiIterator<int>]'
crap.cpp:17:   instantiated from here
/usr/local/lib/gcc/i686-pc-cygwin/3.4.3/../../../../include/c++/3.4.3/bits/stl_a
lgobase.h:369: error: invalid type argument of `unary *'

I understand that this particular example may not be so difficult to
diagnose, but understand this is a greatly simplified example. I have
often written code that results in error output that is over 100 pages
long. Because of the spam, the output is essentially useless and I just
look to what code I just modified to find the source of the problem,
since I know that more than likely there is nothing wrong with the STL
source code reported in the errors.

What I am proposing to fix this is an official way to declare template
specifications so that the compiler will detect if an incompatible type
is passed to a template function or class and simply display that error
and no spam. Here is a hypothetical example:

// Specify a template specification
template<class T>
template interface ti_bidirectional_iterator {
  typedef ti_bidreictional_iterator this_t;
  this_t &operator ++();
  this_t &operator ++(int);
  this_t &operator --();
  this_t &operator --(int);
  T &operator *() const;
  T *operator ->() const;
  bool operator !=(const this_t &) const;
};

// copy_backward only accepts types that comply with
// ti_bidirectional_iterator specification
template<ti_bidirectional_iterator BI1, ti_bidirectional_iterator BI2>
BI2 copy_backward(BI1 first, BI1 last, BI2 result);

...

template<class T>
struct MyBiIterator : public std::iterator<
std::bidirectional_iterator_tag, T> {
  typedef MyBiIterator this_t;
  this_t &operator ++();
  this_t &operator ++(int);
  size_t &operator --(); // Whooops typo
  this_t &operator --(int);
  T &operator *() const;
  T *operator ->() const;

  // Whoops forgot to declare
  // bool operator !=(const this_t &) const;
};

int main()
{
 std::copy_backward(MyBiIterator<int>(), MyBiIterator<int>(),
MyBiIterator<int>());
};

Now when compiled the error will be displayed as MyBiIterator not
complying with the template interface specification
"ti_bidirectional_iterator" and not as errors inside the source for
copy_backward.

With very few exceptions, most template functions and classes can not
be passed just any type. I know for myself at least, that having some
method to specify template specifications would eliminate much STL
related headaches.

Any input on this is appreciated,
Lance Gatlin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Fri, 20 May 2005 01:49:23 GMT
Raw View
"illumanus@yahoo.com" <illumanus@yahoo.com> writes:

> I have often run into cases when using template classes and functions
> that there is a "specification" for types that are allowed to be passed
> to the template.

Commonly known as "requirements," normally expressed in terms of
"concepts."

> The "specification" is assumed to be understood by the
> programmer and if any deviations happen, then member missing, type
> mismatch errors and "instantiated from" spam result. This is
> complicated by the very lengthy type declarations for some standard STL
> classes and the fact that the error report will be sourced to the
> template function or class source code and NOT the code where the error
> really is. It is quite cumbersome to diagnose exactly where the
> deviation from the "specification" occurred. Here is a simplified
> example of passing a type to a template that has an assumed
> "specification":

These problems, among others, are what the proposals for adding
concepts to C++0x are all about, e.g.:
http://www.osl.iu.edu/publications/prints/2005/siek05:_concepts_cpp0x.pdf

In the meantime, you can try a library solution that actually makes
things quite a lot better:
http://www.boost.org/libs/concept_check/concept_check.htm

HTH,
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "illumanus@yahoo.com" <illumanus@yahoo.com>
Date: 20 May 2005 19:30:05 GMT
Raw View
David Abrahams wrote:
> These problems, among others, are what the proposals for adding
> concepts to C++0x are all about, e.g.:
>
http://www.osl.iu.edu/publications/prints/2005/siek05:_concepts_cpp0x.pdf
>
> In the meantime, you can try a library solution that actually makes
> things quite a lot better:
> http://www.boost.org/libs/concept_check/concept_check.htm
>
> HTH,
> --
> Dave Abrahams
> Boost Consulting
> www.boost-consulting.com

Exactly what I was looking for. Thanks for the reply.
R/
Lance Gatlin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]