1

If I create a custom template or class that is supposed to implement a concept defined by a set of traits. How can I test that it actually does implement that concept?

Is there a generally accepted way of doing this for 'traits' classes? (concepts in C++20 are the accepted way in general but I am currently limited to C++14-ish)

Or is it just a case of having to remember?

Some related examples:

  • If I write a fancy pointer that I want to be sure implements pointer_traits. How can I check that it actually does?

  • If I write a custom allocator that I want to be sure implements allocator_traits. How can I check that it actually does?

  • How can I check I've properly implemented iterator_traits?

For example if I implement a 'fancy' pointer along the lines of boost::interprocess::offset_ptr:

I do the normal things:

  • implement & test constructors from T* T&
  • implement & test comparisons <=, <, !=, ==, >=, >=
  • implement & test dereferencing operator* & operator->
  • implement & test assignment
  • implement & test pointer arithmetic ++, --, -, +, +=, -=

To use this type with an allocator we need to implement pointer traits. Is it just a case of implementing to_address() and pointer_to()?

You can make a pointer-like class which does not implement comparisons or pointer arithmetic. Would that still be a valid model of pointer_traits? This question suggests that a valid pointer must implement the random access iterator concept. So the answer would seem to be no. That question is also close to what I'm trying to do.

I expect there are two answers to this. A concepts version and one for earlier iterations of C++. I am interested in both though I am currently limited to C++14.

There is the obvious answer which is to add a test which uses the thing you want to use. So we add an allocator which uses the pointer and add a test using that allocator with an STL type. This is useful and necessary but not necessarily complete or sufficient. It is also relatively speaking an integration test (does X work with Y) rather than a unit test (does X do what X should do).

It is very easy to miss something. For example when implementing smart pointer comparisons it is easy to forget to make the following valid.

nullptr == smartPtr 

Likewise I suspect there are some things that will work if some of the traits are implemented and others that won't if some a not implemented correctly. Hence, I want to add a test or tests to the pointer class's testsuite to ensure it implements everything it needs to implemented to be used with the allocator template.

I also want to better understand what allocator traits, pointer traits and iterator traits are really doing.

Related reading:


Update 1

Speaking of missing things. I already realised I need:

  • explicit operator bool () const;
  • bool operator! () const;
  • rebind
  • using iterator_category = std::random_access_iterator_tag;

Found by attempting to instantiate boost::containers::vector and std::vector. There are some others I am still trying to sort out along with the rebind part.

Bruce Adams
  • 4,953
  • 4
  • 48
  • 111

0 Answers0