diff --git a/Jamfile b/Jamfile index 4cf9462..1647aa6 100644 --- a/Jamfile +++ b/Jamfile @@ -15,6 +15,7 @@ test-suite concept_check [ run where.cpp ] [ compile-fail where_fail.cpp ] + [ compile-fail usage_fail.cpp ] # Backward compatibility tests [ run old_concept_pass.cpp ] diff --git a/Jamfile.v2 b/Jamfile.v2 index 18e51ef..7b7c833 100644 --- a/Jamfile.v2 +++ b/Jamfile.v2 @@ -14,6 +14,7 @@ test-suite concept_check [ run where.cpp ] [ compile-fail where_fail.cpp ] + [ compile-fail usage_fail.cpp ] # Backward compatibility tests [ run old_concept_pass.cpp ] diff --git a/include/boost/concept/usage.hpp b/include/boost/concept/usage.hpp new file mode 100755 index 0000000..399bd4c --- /dev/null +++ b/include/boost/concept/usage.hpp @@ -0,0 +1,32 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_USAGE_DWA2006919_HPP +# define BOOST_CONCEPT_USAGE_DWA2006919_HPP + +# include +# include + +namespace boost { namespace concept { + +# if BOOST_WORKAROUND(__GNUC__, == 2) + +# define BOOST_CONCEPT_USAGE(model) ~model() + +# else + +template +struct usage_requirements +{ + ~usage_requirements() { ((Model*)0)->~Model(); } +}; + +# define BOOST_CONCEPT_USAGE(model) \ + BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements)); \ + ~model() + +# endif + +}} // namespace boost::concept + +#endif // BOOST_CONCEPT_USAGE_DWA2006919_HPP diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 5a127b8..43db342 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -23,9 +23,11 @@ # include # include # include +# include # include # include +# include # include namespace boost @@ -63,7 +65,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Integer(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Integer() + BOOST_CONCEPT_USAGE(Integer) { x.error_type_must_be_an_integer_type(); } @@ -85,7 +87,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) SignedInteger(); // at least 2.96 and 3.4.3 both need this :( #endif - ~SignedInteger() { + BOOST_CONCEPT_USAGE(SignedInteger) { x.error_type_must_be_a_signed_integer_type(); } private: @@ -104,7 +106,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) UnsignedInteger(); // at least 2.96 and 3.4.3 both need this :( #endif - ~UnsignedInteger() { + BOOST_CONCEPT_USAGE(UnsignedInteger) { x.error_type_must_be_an_unsigned_integer_type(); } private: @@ -130,7 +132,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) DefaultConstructible(); // at least 2.96 and 3.4.3 both need this :( #endif - ~DefaultConstructible() { + BOOST_CONCEPT_USAGE(DefaultConstructible) { TT a; // require default constructor ignore_unused_variable_warning(a); } @@ -142,7 +144,7 @@ namespace boost Assignable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Assignable() { + BOOST_CONCEPT_USAGE(Assignable) { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator #endif @@ -164,7 +166,7 @@ namespace boost CopyConstructible(); // at least 2.96 and 3.4.3 both need this :( #endif - ~CopyConstructible() { + BOOST_CONCEPT_USAGE(CopyConstructible) { TT a(b); // require copy constructor TT* ptr = &a; // require address of operator const_constraints(a); @@ -187,7 +189,7 @@ namespace boost SGIAssignable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~SGIAssignable() { + BOOST_CONCEPT_USAGE(SGIAssignable) { TT b(a); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator @@ -211,7 +213,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Convertible(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Convertible() { + BOOST_CONCEPT_USAGE(Convertible) { Y y = x; ignore_unused_variable_warning(y); } @@ -239,7 +241,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) EqualityComparable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~EqualityComparable() { + BOOST_CONCEPT_USAGE(EqualityComparable) { require_boolean_expr(a == b); require_boolean_expr(a != b); } @@ -252,7 +254,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) LessThanComparable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~LessThanComparable() { + BOOST_CONCEPT_USAGE(LessThanComparable) { require_boolean_expr(a < b); } private: @@ -265,7 +267,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Comparable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Comparable() { + BOOST_CONCEPT_USAGE(Comparable) { require_boolean_expr(a < b); require_boolean_expr(a > b); require_boolean_expr(a <= b); @@ -280,7 +282,7 @@ namespace boost BOOST_concept(NAME, (First)(Second)) \ { \ NAME(); \ - ~NAME() { (void)constraints_(); } \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ private: \ bool constraints_() { return a OP b; } \ First a; \ @@ -290,7 +292,7 @@ namespace boost #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ BOOST_concept(NAME, (First)(Second)) \ { \ - ~NAME() { (void)constraints_(); } \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ private: \ bool constraints_() { return a OP b; } \ First a; \ @@ -303,7 +305,7 @@ namespace boost BOOST_concept(NAME, (Ret)(First)(Second)) \ { \ NAME(); \ - ~NAME() { (void)constraints_(); } \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ private: \ Ret constraints_() { return a OP b; } \ First a; \ @@ -313,7 +315,7 @@ namespace boost #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ BOOST_concept(NAME, (Ret)(First)(Second)) \ { \ - ~NAME() { (void)constraints_(); } \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ private: \ Ret constraints_() { return a OP b; } \ First a; \ @@ -342,7 +344,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Generator(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Generator() { test(is_void()); } + BOOST_CONCEPT_USAGE(Generator) { test(is_void()); } private: void test(boost::mpl::false_) @@ -365,7 +367,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) UnaryFunction(); // at least 2.96 and 3.4.3 both need this :( #endif - ~UnaryFunction() { test(is_void()); } + BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void()); } private: void test(boost::mpl::false_) @@ -389,7 +391,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) BinaryFunction(); // at least 2.96 and 3.4.3 both need this :( #endif - ~BinaryFunction() { test(is_void()); } + BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void()); } private: void test(boost::mpl::false_) { @@ -413,7 +415,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) UnaryPredicate(); // at least 2.96 and 3.4.3 both need this :( #endif - ~UnaryPredicate() { + BOOST_CONCEPT_USAGE(UnaryPredicate) { require_boolean_expr(f(arg)); // require operator() returning bool } private: @@ -426,7 +428,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( #endif - ~BinaryPredicate() { + BOOST_CONCEPT_USAGE(BinaryPredicate) { require_boolean_expr(f(a, b)); // require operator() returning bool } private: @@ -442,7 +444,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Const_BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Const_BinaryPredicate() { + BOOST_CONCEPT_USAGE(Const_BinaryPredicate) { const_constraints(f); } private: @@ -463,7 +465,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) AdaptableGenerator(); // at least 2.96 and 3.4.3 both need this :( #endif - ~AdaptableGenerator() + BOOST_CONCEPT_USAGE(AdaptableGenerator) { BOOST_CONCEPT_ASSERT((Convertible)); } diff --git a/usage_fail.cpp b/usage_fail.cpp new file mode 100755 index 0000000..29796b9 --- /dev/null +++ b/usage_fail.cpp @@ -0,0 +1,22 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +template +struct StringInitializable +{ + typedef int associated; + BOOST_CONCEPT_USAGE(StringInitializable) + { + T x = "foo"; + } +}; + +// Test that accessing an associated type will actually exercise usage +// requirements +typedef StringInitializable::associated tee; + + +