Boost Concept Check Library Kasper Egdø and Konstantin Barkaia Department of Computer Science University of Copenhagen Boost Concept Check Library p.1/19
Eksempel #include <list> #include <algorithm> int main(int, char*[]) std::list<int> v; std::stable_sort(v.begin(), v.end()); return 0; } Boost Concept Check Library p.2/19
Informativ fejlbesked /usr/.../stl_algo.h: In function void std:: inplace_stable_sort( _RandomAccessIter, _RandomAccessIter) [with _RandomAccessIter = std::_list_iterator<int, int&, int*>] : /usr/.../stl_algo.h:2446: instantiated from void std::stable_sort(_randomaccessiter, _RandomAccessIter) [with _RandomAccessIter = std::_list_iterator<int, int&, int*>] lucy_lou.cpp:6: instantiated from here /usr/.../stl_algo.h:2226: error: no match for operator- in last - first Boost Concept Check Library p.3/19
Concepts Et koncept beskriver den semantik en type skal have I praksis er et koncept en samling af funktioner som typen skal implementere F.eks. kræver std::stable_sort at den modtager RandomAccessIterators. En concept check klasse kan undersøge om en given type implementerer et givent concept Boost implementerer concept check klasser for samtlige koncepter i STL InputIterator ForwardIterator Assignable LessThenComparable... Boost Concept Check Library p.4/19
Ingen brug af concept checks template <class RandomAccessIterator> void stable_sort(randomaccessiterator first, RandomAccessIterator last)... } Boost Concept Check Library p.5/19
Brug af concept checks template <class RandomAccessIterator> void stable_sort(randomaccessiterator first, RandomAccessIterator last) boost::function_requires< boost::randomaccessiteratorconcept< RandomAccessIterator> >(); typedef typename std::iterator_traits< RandomAccessIter>::value_type value_type; } function_requires< LessThanComparableConcept< value_type> >();... Boost Concept Check Library p.6/19
Bedre fejlbesked (?) /vol/.../boost/concept_check.hpp: In member function void boost::comparableconcept<tt>::constraints [with TT = std::_list_iterator<int, int&, int*>] : /vol/.../boost/concept_check.hpp:48: instantiated from void boost::function_requires(boost::mpl::ident [with Concept = boost::comparableconcept<std::_list_iterator<int, /vol/.../boost/concept_check.hpp:633: instantiated from void boost::randomaccessiteratorconcept<tt>::co [with TT = std::_list_iterator<int, int&, int*>] /vol/.../boost/concept_check.hpp:48: instantiated from void boost::function_requires(boost::mpl::ident [with Concept = boost::randomaccessiteratorconcept< std::_list_iterator<int, int&, int*> >] fejltest.cpp:8: instantiated from void stable_sort(t, T) [with T = std::_list_iterator<int, int&, int*>] fejltest.cpp:14: instantiated from here. Boost Concept Check Library p.7/19
Brug af concept checks II template<class T> class X BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);... }; Boost Concept Check Library p.8/19
Eksempel: BidirectionalIteratorConcept template <class TT> struct BidirectionalIteratorConcept void constraints() function_requires< ForwardIteratorConcept<TT> >(); typedef typename std::iterator_traits<tt>::iterator_category C; function_requires< ConvertibleConcept<C, std::bidirectional_iterator_tag> >(); --i; // require predecrement operator i--; // require postdecrement operator } TT i; }; Boost Concept Check Library p.9/19
Implementation template <class RandomAccessIterator> void stable_sort(randomaccessiterator first, RandomAccessIterator last) boost::function_requires< boost::randomaccessiteratorconcept< RandomAccessIterator> >();... } template <class Concept> void function_requires() void (Concept::*x)() = Concept::constraints; ignore_unused_variable_warning(x); } Ved at tage adressen af constraints funktionen tvinges oversættelse af denne constraints kaldes aldrig Boost Concept Check Library p.10/19
Implementation #define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ typedef void (ns::concept <type_var>::* func##type_var##concept)(); \ template <func##type_var##concept Tp1_> \ struct concept_checking_##type_var##concept }; \ typedef concept_checking_##type_var##concept< \ BOOST_FPTR ns::concept<type_var>::constraints> \ concept_checking_typedef_##type_var##concept Boost Concept Check Library p.11/19
Makroen ekspanderet template<class T> class X BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);... }; template <typename T> class X typedef void (boost::lessthancomparableconcept <T>::* A)(); template <A Tp1_> struct B }; typedef B<boost::LessThanComparableConcept<T>::constraints> C;... }; Boost Concept Check Library p.12/19
Arketyper Bruges til at kontrollere at en generisk konstruktion sætter de rette begrænsninger. F.eks. at unique_copy ikke trækker to iteratorer fra hinanden samtidig med at iteratorerne er defineret til at være ForwardIterators. Boost Concept Check Library p.13/19
Eksempel på brug af arketyper Følgende tester om unique_copy kun anvder funktionalitet som findes i InputIteratorer og OutputIterator som itererer over EqualityComparable og Assignable typer: boost::detail::dummy_constructor dummy_cons; typedef boost::equality_comparable_archetype< boost::assignable_archetype<> > ValueType; boost::input_iterator_archetype<valuetype> ri; boost::output_iterator_archetype<valuetype> ro(dummy_cons); unique_copy(ri, ri, ro); } ValueType er EqualityComparable ri er en InputIterator af type ValueType ro er en OutputIterator af type ValueType Boost Concept Check Library p.14/19
Implementation af arketyper template <class T = int> class null_archetype private: null_archetype() } null_archetype(const null_archetype&) } null_archetype& operator=(const null_archetype&) return *this; } public: null_archetype(detail::dummy_constructor) } }; Boost Concept Check Library p.15/19
Implementation af arketyper II template <class Base = null_archetype<> > class default_constructible_archetype : public Base public: default_constructible_archetype() : Base(static_object<detail::dummy_constructor>::get()) } default_constructible_archetype(detail::dummy_constructor x) : Ba }; Boost Concept Check Library p.16/19
Implementation af arketyper III template <class T> class forward_iterator_archetype public: typedef forward_iterator_archetype self; public: typedef std::forward_iterator_tag iterator_category; typedef T value_type; typedef const T& reference; typedef T const* pointer; typedef std::ptrdiff_t difference_type; forward_iterator_archetype() } self& operator=(const self&) return *this; } bool operator==(const self&) const return true; } bool operator!=(const self&) const return true; } reference operator*() const return static_object<t>::get(); } self& operator++() return *this; } self operator++(int) return *this; } }; Boost Concept Check Library p.17/19
Diverse Koncepter er et compile-tids fænomen Ingen runtime cost Har ingen effekt for betydningen af ens program Boost Concept Check Library p.18/19
Konklusion Concept checks gør det lidt simplere at forstå hvorfor ens kode ikke virker Arketyper kan hjælpe en med at finde fejl i ens implementation af generiske funktioner og containere Boost Concept Check Library p.19/19