
Hello, I work on big software project that is ported to several platforms/compilers, including Linux,Solaris/GCC 2.95.2,3.0.4); Windows/MSVC 6.0; AIX/VisualAge; MacOS X / GCC 2.95.2 (Apple). Recently, I decided to make use of Boost library (v 1.28) and the first thing I tried was Boost Concept Check Library (BCCL). Unfortunately, the use of the library wasn't as smooth as I expected, namely, with respect to BOOST_CLASS_REQUIRES macro. Thus, I'd like to submit a couple of observations and one proposal regarding usage of this macro. Let's start with observations: following is the snippet from <boost/concept_check.hpp> header: [code // The BOOST_CLASS_REQUIRES macros use function pointers as // template parameters, which VC++ does not support. #if defined(BOOST_NO_FUNCTION_PTR_TEMPLATE_PARAMETERS) #define BOOST_CLASS_REQUIRES(type_var, concept) .... #else #define BOOST_CLASS_REQUIRES(type_var, concept) \ typedef void (concept <type_var>::* func##type_var##concept)(); \ .... end code] As you could see, BOOST_CLASS_REQUIRES macros evaluate to nothing if BOOST_NO_FUNCTION_PTR_TEMPLATE_PARAMETERS symbol is defined. But, to my great surprise, I didn't find any more references to BOOST_NO_FUNCTION_PTR_TEMPLATE_PARAMETERS symbol throughout the Boost library. Moreover, the above comment about VC++ not supporting function pointers as template parameters is wrong (at least for MSVC 6.0 with SP5). Not to be unfounded, I will provide following sample program successfully compiled and run under MSVC 6.0 with SP5: [code #include <iostream> using namespace std; typedef void(*FP)(); template <FP T> class X { FP fp_; public: X() : fp_(T) {} void print() const { cout << fp_ << endl; } }; void f() {} int main(int, char**) { X<&f> x1; x1.print(); return 0; } end code] The same is true for pointers to member functions of both ordinary and template classes. OK, this observation could be treated as "cosmetic" one, but the following won't. Let's look at the definition of BOOST_CLASS_REQUIRES macro: [code #define BOOST_CLASS_REQUIRES(type_var, concept) \ typedef void (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 concept <type_var>::constraints> \ concept_checking_typedef_##type_var##concept end code] and at a typical usage of this macro (taken from Boost documentation): [code template <class T> struct generic_library_class { BOOST_CLASS_REQUIRES(T, EqualityComparableConcept); // ... }; end code] Here, the "EqualityComparableConcept" is a concept checking class defined in the "boost" namespace. OK, that's great and works fine until "generic_library_class" is also declared in the "boost" namespace. Let's now suppose "generic_library_class" is declared in namespace "ns1". Then, BOOST_CLASS_REQUIRES macro evaluates to following: [code namespace ns1 { template <class T> struct generic_library_class { typedef void (EqualityComparableConcept <T>::* funcTEqualityComparableConcept)(); ... }; } end code] Did you see the problem places? Yes, it's where "concept" parameter of the macro is substituted for "EqualityComparableConcept". This name is not declared in the namespace "ns1"! The first itch could be to specify "boost::EqualityComparableConcept" as a value of the second parameter of the macro, but, "not so fast, Skywalker!" - in this case we will end up with "funcTboost::EqualityComparableConcept" name for the pointer to member function that is not a legal name of C/C++ identifier. Someone could say "What a big deal?! Just write 'using namespace boost;' or 'using boost::EqualityComparableConcept;' just before declaring 'generic_library_class'.". Well, the declaration of "generic_library_class" seems to be in the header, right? And what do you think about writing "using-directives" in header files? Yes, right, - it's evil! Especially for large production code. Just check your favorite C++ book. Though, the use of "using-declarations" in headers is a moot point, I also consider it as evil for the same reasons as for "using- directives". Anyway, "using-declarations" won't help us, - they just don't work under MSVC 6.0 in our case. So, what do we have, - "exclusive circle"? I hope not. Finally, I got to the proposal that should help us to eliminate defects of the macro and to obviate above-stated difficulties. What if to add one more parameter, say, "ns", to the BOOST_CLASS_REQUIRES macro to pass the name of the namespace the concept checking class belongs to? Let's look at the new definition of the macro: [code #define BOOST_CLASS_REQUIRES(type_var, ns, concept) \ typedef void (ns::concept <type_var>::* func##type_var##ns##concept) (); \ template <func##type_var##ns##concept _Tp1> \ struct concept_checking_##type_var##ns##concept { }; \ typedef concept_checking_##type_var##ns##concept< \ BOOST_FPTR ns::concept <type_var>::constraints> \ concept_checking_typedef_##type_var##ns##concept; end code] and at it's usage: [code namespace ns1 { template <class T> struct generic_library_class { BOOST_CLASS_REQUIRES(T, boost, EqualityComparableConcept); // ... }; } end code] that will evaluate to the following: [code namespace ns1 { template <class T> struct generic_library_class { typedef void (boost::EqualityComparableConcept <T>::* funcTboostEqualityComparableConcept)(); ... }; } end code] That's it. Moreover, this solution does not suffer from yet another drawback inherent to the original one, viz, name clashing when using in the same class concept checking classes with the same name, but from different namespaces. The only issue I could see with my suggestion was impossibility to use concept checking classes declared at the global scope, but, I hope nobody would think of such thing, because it's evil (sorry for repetition). I hope the proposed solution will increase usability of the BCCL. Best regards, Igor Bashkirov.