[concept] forward declarations and `BOOST_CONCEPT_REQUIRES()`

Hello all, Can I forward declare a function template that checks concepts using `BOOST_CONCEPT_REQUIRES()`? In the following example, MSVC gives me an ambiguous call error when I try to do that... (I have not yet tried other compilers). Example "c00.cpp": #include <boost/concept/requires.hpp> #include <boost/concept_check.hpp> #include <vector> // (1) Forward declaration with concepts. template<class Iter, class T> BOOST_CONCEPT_REQUIRES( ((boost::ForwardIterator<Iter>)) ((boost::EqualityComparable<T>)) , (bool) ) all_equals(Iter first, Iter last, const T& val); // (2) Actual definition. template<class Iter, class T> BOOST_CONCEPT_REQUIRES( ((boost::ForwardIterator<Iter>)) ((boost::EqualityComparable<T>)) , (bool) ) all_equals(Iter first, Iter last, const T& val) { for (Iter i = first; i < last; ++i) { if (*i != val) return false; } return true; } int main() { std::vector<double> v; // MSVC error: Cannot resolved ambiguous call between (1) and (2). all_equals(v.begin(), v.end(), double()); return 0; } MSVC error: Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. c00.cpp c00.cpp(28) : error C2668: 'all_equals' : ambiguous call to overloaded function c00.cpp(18): could be 'bool all_equals<std::_Vector_iterator<_Ty,_Alloc>,double>(Iter,Iter,const T &)' with [ _Ty=double, _Alloc=std::allocator<double>, Iter=std::_Vector_iterator<double,std::allocator<double>>, T=double ] c00.cpp(11): or 'bool all_equals<std::_Vector_iterator<_Ty,_Alloc>,double>(Iter,Iter,const T &)' with [ _Ty=double, _Alloc=std::allocator<double>, Iter=std::_Vector_iterator<double,std::allocator<double>>, T=double ] while trying to match the argument list '(std::_Vector_iterator<_Ty,_Alloc>, std::_Vector_iterator<_Ty,_Alloc>, double)' with [ _Ty=double, _Alloc=std::allocator<double> ] Thank you very much. -- Lorenzo

On Mon, Aug 9, 2010 at 1:03 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
Can I forward declare a function template that checks concepts using `BOOST_CONCEPT_REQUIRES()`?
In the following example, MSVC gives me an ambiguous call error when I try to do that... (I have not yet tried other compilers).
c00.cpp(28) : error C2668: 'all_equals' : ambiguous call to overloaded function c00.cpp(18): could be 'bool all_equals<std::_Vector_iterator<_Ty,_Alloc>,double>(Iter,Iter,const T &)' with [ _Ty=double, _Alloc=std::allocator<double>, Iter=std::_Vector_iterator<double,std::allocator<double>>, T=double ] c00.cpp(11): or 'bool all_equals<std::_Vector_iterator<_Ty,_Alloc>,double>(Iter,Iter,const T &)' with [ _Ty=double, _Alloc=std::allocator<double>, Iter=std::_Vector_iterator<double,std::allocator<double>>, T=double ] while trying to match the argument list '(std::_Vector_iterator<_Ty,_Alloc>, std::_Vector_iterator<_Ty,_Alloc>, double)' with [ _Ty=double, _Alloc=std::allocator<double> ]
Thank you very much.
Just from looking at the error message this would seem to be a cut-and-dried case of bugs in the compiler. The "overloads" it is saying are ambiguous are identical, meaning they're really just one thing. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Mon, Aug 9, 2010 at 10:00 PM, Dave Abrahams <dave@boostpro.com> wrote:
On Mon, Aug 9, 2010 at 1:03 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
Can I forward declare a function template that checks concepts using `BOOST_CONCEPT_REQUIRES()`?
In the following example, MSVC gives me an ambiguous call error when I try to do that... (I have not yet tried other compilers).
c00.cpp(28) : error C2668: 'all_equals' : ambiguous call to overloaded function c00.cpp(18): could be 'bool all_equals<std::_Vector_iterator<_Ty,_Alloc>,double>(Iter,Iter,const T &)' with [ _Ty=double, _Alloc=std::allocator<double>, Iter=std::_Vector_iterator<double,std::allocator<double>>, T=double ] c00.cpp(11): or 'bool all_equals<std::_Vector_iterator<_Ty,_Alloc>,double>(Iter,Iter,const T &)' with [ _Ty=double, _Alloc=std::allocator<double>, Iter=std::_Vector_iterator<double,std::allocator<double>>, T=double ] while trying to match the argument list '(std::_Vector_iterator<_Ty,_Alloc>, std::_Vector_iterator<_Ty,_Alloc>, double)' with [ _Ty=double, _Alloc=std::allocator<double> ]
Thank you very much.
Just from looking at the error message this would seem to be a cut-and-dried case of bugs in the compiler. The "overloads" it is saying are ambiguous are identical, meaning they're really just one thing.
Yes, I noticed the same thing. I cannot try the code on other compilers at the moment, it would be great if anyone from this mailing list could do that and let me know... Even assuming this is a MSVC bug, is there a workaround for it? I have been thinking to do the following: // (1) Forward declaration without concepts. template<class Iter, class T> bool all_equals(Iter first, Iter last, const T& val); // (2) Actual definition with concepts. template<class Iter, class T> BOOST_CONCEPT_REQUIRES( ((boost::ForwardIterator<Iter>)) ((boost::EqualityComparable<T>)) , (bool) ) all_equals(Iter first, Iter last, const T& val) { ... // Implementation. } But I do not think this will work because the first declaration is not guarded by the concepts so it will only generate a linker-time error "missing definition" if the T does not satisfy the concepts (correct?). However, I do not really understand the Boost.ConceptCheck/EnableIf machinery so there might be a way around this issue. Thank you again. -- Lorenzo

On 8/10/2010 1:05 PM, Lorenzo Caminiti wrote:
Yes, I noticed the same thing. I cannot try the code on other compilers at the moment, it would be great if anyone from this mailing list could do that and let me know...
I was able to get your code to compile and run fine on several different versions of gcc. I can't comment on workarounds for MSVC or if this bug appears only in specific version of MSVC. Tim Timothy Moore Montecito Software LLC http://www.montecito-software.com

On 8/10/2010 10:05 PM, Lorenzo Caminiti wrote:
On Mon, Aug 9, 2010 at 10:00 PM, Dave Abrahams<dave@boostpro.com> wrote:
Just from looking at the error message this would seem to be a cut-and-dried case of bugs in the compiler. The "overloads" it is saying are ambiguous are identical, meaning they're really just one thing.
Yes, I noticed the same thing. I cannot try the code on other compilers at the moment, it would be great if anyone from this mailing list could do that and let me know...
Even assuming this is a MSVC bug, is there a workaround for it?
For what it's worth. On MSVC10 your code only fails to build in Debug mode for me. There's a Workaround already in requires.hpp that only triggers if BOOST_MSVC < 1300 or #ifdef(NDEBUG). Adding || BOOST_WORKAROUND(BOOST_MSVC, == 1600) (obviously 1600 is my _MSC_VER) gets rid of the problem for me. I don't know why the workaround has been disabled for debug builds and I don't know if enabling it that way wreaks havoc somewhere else. Have a nice day, Stefan #if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300) || BOOST_WORKAROUND(BOOST_MSVC, == 1600) # define BOOST_CONCEPT_REQUIRES(models, result) \ typename ::boost::parameter::aux::unaryfunptr_arg_type<void(*)result>::type

Please note that NDEBUG controls the assert() macro. NDEBUG can be defined or undefined by the user at will, even repeatedly within a translation unit (see C99 7.2/1). _DEBUG is defined by VC when compiling in debug mode (with the /MTd or /MDd options), and not when compiling in release mode (with the /MT or /MD options). It must not be defined or undefined by the user. (Technically, defining it when it's already defined, and vice versa, is harmless, but the user shouldn't do that. The IDE does that for its own reasons.) Despite their similar names, NDEBUG and _DEBUG are totally different. It sounds like you shouldn't be testing NDEBUG here. (If VC10, aka 1600, is doing something wrong here, I'd like to know about it - with a self-contained repro.) Stephan T. Lavavej Visual C++ Libraries Developer -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Stefan van Kessel Sent: Tuesday, August 10, 2010 2:02 PM To: boost@lists.boost.org Subject: Re: [boost] [concept] forward declarations and `BOOST_CONCEPT_REQUIRES()` On 8/10/2010 10:05 PM, Lorenzo Caminiti wrote:
On Mon, Aug 9, 2010 at 10:00 PM, Dave Abrahams<dave@boostpro.com> wrote:
Just from looking at the error message this would seem to be a cut-and-dried case of bugs in the compiler. The "overloads" it is saying are ambiguous are identical, meaning they're really just one thing.
Yes, I noticed the same thing. I cannot try the code on other compilers at the moment, it would be great if anyone from this mailing list could do that and let me know...
Even assuming this is a MSVC bug, is there a workaround for it?
For what it's worth. On MSVC10 your code only fails to build in Debug mode for me. There's a Workaround already in requires.hpp that only triggers if BOOST_MSVC < 1300 or #ifdef(NDEBUG). Adding || BOOST_WORKAROUND(BOOST_MSVC, == 1600) (obviously 1600 is my _MSC_VER) gets rid of the problem for me. I don't know why the workaround has been disabled for debug builds and I don't know if enabling it that way wreaks havoc somewhere else. Have a nice day, Stefan #if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300) || BOOST_WORKAROUND(BOOST_MSVC, == 1600) # define BOOST_CONCEPT_REQUIRES(models, result) \ typename ::boost::parameter::aux::unaryfunptr_arg_type<void(*)result>::type _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 8/10/2010 11:20 PM, Stephan T. Lavavej wrote:
Please note that NDEBUG controls the assert() macro. NDEBUG can be defined or undefined by the user at will, even repeatedly within a translation unit (see C99 7.2/1).
_DEBUG is defined by VC when compiling in debug mode (with the /MTd or /MDd options), and not when compiling in release mode (with the /MT or /MD options). It must not be defined or undefined by the user. (Technically, defining it when it's already defined, and vice versa, is harmless, but the user shouldn't do that. The IDE does that for its own reasons.)
Despite their similar names, NDEBUG and _DEBUG are totally different. It sounds like you shouldn't be testing NDEBUG here.
(If VC10, aka 1600, is doing something wrong here, I'd like to know about it - with a self-contained repro.)
Stephan T. Lavavej Visual C++ Libraries Developer
My mistake. Whether the build mode is debug or not (/MTd || /MDd) is unrelated. It was just my first assumption because switching to release mode made it compile (since it per default includes /D "NDEBUG"). Since the #define for BOOST_CONCEPT_REQUIRES that is switched to under those conditions discards the models i.e. concept requirements, I suppose it was a design decision for the BOOST_CONCEPT_REQUIRES to act like assert in respect to whether it actually does any testing in presence of NDEBUG.

On 8/10/2010 11:20 PM, Stephan T. Lavavej wrote:
(If VC10, aka 1600, is doing something wrong here, I'd like to know about it - with a self-contained repro.)
This is what I think it boils down to: template <int check> struct IntToVoid { typedef void type; }; template <typename T> struct TypeToZero { enum { value = 0 }; }; template <typename T> struct Empty { }; template<typename T> typename IntToVoid<(TypeToZero<Empty<T> >::value ) >::type foo(); template<typename T> typename IntToVoid<(TypeToZero<Empty<T> >::value ) >::type foo() {} int main() { foo<int>(); return 0; } 1>------ Build started: Project: test, Configuration: Debug x64 ------ 1> main.cpp 1>main.cpp(31): error C2668: 'foo' : ambiguous call to overloaded function 1> main.cpp(25): could be 'IntToBool<check>::type foo<int>(void)' 1> with 1> [ 1> check=0 1> ] 1> main.cpp(20): or 'IntToBool<check>::type foo<int>(void)' 1> with 1> [ 1> check=0 1> ] 1> while trying to match the argument list '(void)' ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== If one omits the () around TypeToZero<Empty<T> >::value, it compiles just fine: template<typename T> typename IntToVoid<TypeToZero<Empty<T> >::value >::type foo(); template<typename T> typename IntToVoid<TypeToZero<Empty<T> >::value >::type foo() {}

Thanks. I've filed this as internal bug number 28784. (It may or may not meet the compiler's triage bar.) STL -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Stefan van Kessel Sent: Tuesday, August 10, 2010 5:00 PM To: boost@lists.boost.org Subject: Re: [boost] [concept] forward declarations and `BOOST_CONCEPT_REQUIRES()` On 8/10/2010 11:20 PM, Stephan T. Lavavej wrote:
(If VC10, aka 1600, is doing something wrong here, I'd like to know about it - with a self-contained repro.)
This is what I think it boils down to: template <int check> struct IntToVoid { typedef void type; }; template <typename T> struct TypeToZero { enum { value = 0 }; }; template <typename T> struct Empty { }; template<typename T> typename IntToVoid<(TypeToZero<Empty<T> >::value ) >::type foo(); template<typename T> typename IntToVoid<(TypeToZero<Empty<T> >::value ) >::type foo() {} int main() { foo<int>(); return 0; } 1>------ Build started: Project: test, Configuration: Debug x64 ------ 1> main.cpp 1>main.cpp(31): error C2668: 'foo' : ambiguous call to overloaded function 1> main.cpp(25): could be 'IntToBool<check>::type foo<int>(void)' 1> with 1> [ 1> check=0 1> ] 1> main.cpp(20): or 'IntToBool<check>::type foo<int>(void)' 1> with 1> [ 1> check=0 1> ] 1> while trying to match the argument list '(void)' ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== If one omits the () around TypeToZero<Empty<T> >::value, it compiles just fine: template<typename T> typename IntToVoid<TypeToZero<Empty<T> >::value >::type foo(); template<typename T> typename IntToVoid<TypeToZero<Empty<T> >::value >::type foo() {} _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Tue, Aug 10, 2010 at 5:01 PM, Stefan van Kessel <van_kessel@freenet.de> wrote:
On 8/10/2010 10:05 PM, Lorenzo Caminiti wrote:
On Mon, Aug 9, 2010 at 10:00 PM, Dave Abrahams<dave@boostpro.com> wrote:
Just from looking at the error message this would seem to be a cut-and-dried case of bugs in the compiler. The "overloads" it is saying are ambiguous are identical, meaning they're really just one thing.
Yes, I noticed the same thing. I cannot try the code on other compilers at the moment, it would be great if anyone from this mailing list could do that and let me know...
Even assuming this is a MSVC bug, is there a workaround for it?
For what it's worth. On MSVC10 your code only fails to build in Debug mode for me. There's a Workaround already in requires.hpp that only triggers if BOOST_MSVC < 1300 or #ifdef(NDEBUG). Adding || BOOST_WORKAROUND(BOOST_MSVC, == 1600) (obviously 1600 is my _MSC_VER) gets rid of the problem for me. I don't know why the workaround has been disabled for debug builds and I don't know if enabling it that way wreaks havoc somewhere else.
Have a nice day, Stefan
#if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300) || BOOST_WORKAROUND(BOOST_MSVC, == 1600)
# define BOOST_CONCEPT_REQUIRES(models, result) \ typename ::boost::parameter::aux::unaryfunptr_arg_type<void(*)result>::type
Could you please make note of this in a Trac ticket? Otherwise it's liable to get lost. Thanks, -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 8/11/2010 12:28 AM, Dave Abrahams wrote:
Could you please make note of this in a Trac ticket? Otherwise it's liable to get lost.
Done. The Ticket # is 4526. With very little testing, the following code fixes the issue for me on MSVC10. I just tried avoiding non-type template arguments. #elif BOOST_WORKAROUND(BOOST_MSVC, == 1600) template <typename T1, typename T2> struct requires_msvc10 { typedef typename T2::type type; }; template <typename T> struct relay_type_msvc10 { typedef T type; }; #define BOOST_CONCEPT_STRIP_PARENS(x) x #define BOOST_CONCEPT_TEST_SINGLE_REQUIREMENT(x) decltype(::boost::_requires_<void(*) (x) >::value) #define BOOST_CONCEPT_CLOSE_TEMPLATE(r, data, elem) > #define BOOST_CONCEPT_OPEN_TEMPLATE(r, data, i, elem) ::boost::requires_msvc10< BOOST_CONCEPT_TEST_SINGLE_REQUIREMENT elem , #define BOOST_CONCEPT_REQUIRES(models , result) \ typename \ BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_OPEN_TEMPLATE, 0, models) \ ::boost::relay_type_msvc10< BOOST_CONCEPT_STRIP_PARENS result> \ BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_CLOSE_TEMPLATE, 0, models) \ ::type

On Wed, Aug 11, 2010 at 2:27 AM, Stefan van Kessel <van_kessel@freenet.de> wrote:
On 8/11/2010 12:28 AM, Dave Abrahams wrote:
Could you please make note of this in a Trac ticket? Otherwise it's liable to get lost.
Done. The Ticket # is 4526.
With very little testing, the following code fixes the issue for me on MSVC10. I just tried avoiding non-type template arguments.
Thanks a lot! I am trying to use your code to implement a workaround within my library and eventually remove it when/if the workaround is implemented within Boost.ConceptCheck. I have a couple of questions below.
#elif BOOST_WORKAROUND(BOOST_MSVC, == 1600)
I have this error on _MSC_VER 1400 (MSVC8?) so I was thinking to use: #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) ... // Workaround wrapper for BOOST_CONCEPT_CHECK following your code below. #else ... // Original BOOST_CONCEPT_CHECK with no workaround. #endif
template <typename T1, typename T2> struct requires_msvc10 { typedef typename T2::type type; };
template <typename T> struct relay_type_msvc10 { typedef T type; };
#define BOOST_CONCEPT_STRIP_PARENS(x) x #define BOOST_CONCEPT_TEST_SINGLE_REQUIREMENT(x) \ decltype(::boost::_requires_<void(*) (x) >::value)
I don't have `decltype()` (I think that is a C++0x feature...). What shall I use instead? Boost.TypeOf somehow? Can you please sketch the code without `decltype()`?
#define BOOST_CONCEPT_CLOSE_TEMPLATE(r, data, elem) > #define BOOST_CONCEPT_OPEN_TEMPLATE(r, data, i, elem) \ ::boost::requires_msvc10< BOOST_CONCEPT_TEST_SINGLE_REQUIREMENT elem ,
#define BOOST_CONCEPT_REQUIRES(models , result) \ typename \ BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_OPEN_TEMPLATE, 0, models) \ ::boost::relay_type_msvc10< BOOST_CONCEPT_STRIP_PARENS result> \ BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_CLOSE_TEMPLATE, 0, models) \ ::type
-- Lorenzo

On 8/11/2010 8:44 PM, Lorenzo Caminiti wrote:
I have this error on _MSC_VER 1400 (MSVC8?) so I was thinking to use:
#if BOOST_WORKAROUND(BOOST_MSVC,>= 1400) ... // Workaround wrapper for BOOST_CONCEPT_CHECK following your code below. #else ... // Original BOOST_CONCEPT_CHECK with no workaround. #endif
That is the general idea but I'd go with #elif BOOST_WORKAROUND(BOOST_MSVC, <= 1600) && BOOST_WORKAROUND(BOOST_MSVC, >= 1400) since I'm still hopeful that in the upcoming MSVC release the workaround won't be necessary.
template<typename T1, typename T2> struct requires_msvc10 { typedef typename T2::type type; };
template<typename T> struct relay_type_msvc10 { typedef T type; };
#define BOOST_CONCEPT_STRIP_PARENS(x) x #define BOOST_CONCEPT_TEST_SINGLE_REQUIREMENT(x) \ decltype(::boost::_requires_<void(*) (x)>::value)
I don't have `decltype()` (I think that is a C++0x feature...). What shall I use instead? Boost.TypeOf somehow? Can you please sketch the code without `decltype()`?
Actually the decltype isn't required at all. It is just a remnant of a previous attempt where without accessing ::boost::_requires_<>::value the compiler didn't seem to instantiate the _requires_ template. I should have double checked. I do not have Visual Studio 2005 (MSVC8) installed right now but on Visual Studio 2008 (MSVC9) it compiles when simply leaving out the decltype and ::value. Here is a link to a patchfile: https://svn.boost.org/trac/boost/attachment/ticket/4526/pathfile2.patch Have a nice day, Stefan

At Wed, 11 Aug 2010 22:54:21 +0200, Stefan van Kessel wrote:
On 8/11/2010 8:44 PM, Lorenzo Caminiti wrote:
I have this error on _MSC_VER 1400 (MSVC8?) so I was thinking to use:
#if BOOST_WORKAROUND(BOOST_MSVC,>= 1400) ... // Workaround wrapper for BOOST_CONCEPT_CHECK following your code below. #else ... // Original BOOST_CONCEPT_CHECK with no workaround. #endif
That is the general idea but I'd go with #elif BOOST_WORKAROUND(BOOST_MSVC, <= 1600) && BOOST_WORKAROUND(BOOST_MSVC, >= 1400) since I'm still hopeful that in the upcoming MSVC release the workaround won't be necessary.
Normally in a case like this we use BOOST_TESTED_AT, so we can easily find and test workarounds that may no longer be needed. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Wed, Aug 11, 2010 at 5:03 PM, David Abrahams <dave@boostpro.com> wrote:
At Wed, 11 Aug 2010 22:54:21 +0200, Stefan van Kessel wrote:
On 8/11/2010 8:44 PM, Lorenzo Caminiti wrote:
I have this error on _MSC_VER 1400 (MSVC8?) so I was thinking to use:
#if BOOST_WORKAROUND(BOOST_MSVC,>= 1400) ... // Workaround wrapper for BOOST_CONCEPT_CHECK following your code below. #else ... // Original BOOST_CONCEPT_CHECK with no workaround. #endif
That is the general idea but I'd go with #elif BOOST_WORKAROUND(BOOST_MSVC, <= 1600) && BOOST_WORKAROUND(BOOST_MSVC, >= 1400) since I'm still hopeful that in the upcoming MSVC release the workaround won't be necessary.
Normally in a case like this we use BOOST_TESTED_AT, so we can easily find and test workarounds that may no longer be needed.
On Wed, Aug 11, 2010 at 4:54 PM, Stefan van Kessel <van_kessel@freenet.de> wrote:
On 8/11/2010 8:44 PM, Lorenzo Caminiti wrote:
I don't have `decltype()` (I think that is a C++0x feature...). What shall I use instead? Boost.TypeOf somehow? Can you please sketch the code without `decltype()`?
Actually the decltype isn't required at all. It is just a remnant of a previous attempt where without accessing ::boost::_requires_<>::value the compiler didn't seem to instantiate the _requires_ template. I should have double checked.
I do not have Visual Studio 2005 (MSVC8) installed right now but on Visual Studio 2008 (MSVC9) it compiles when simply leaving out the decltype and ::value.
Here is a link to a patchfile: https://svn.boost.org/trac/boost/attachment/ticket/4526/pathfile2.patch
Thanks a lot, this fully solves my problem. I have implemented this workaround in my library essentially using the code from this patch (with a some renaming) and guarded it with `BOOST_TESTED_AT()` -- code listed below. I think the use of `BOOST_PP_SEQ_FOR_EACH_I()` in the patch is not necessary so I replaced it with just `BOOST_PP_SEQ_FOR_EACH()`. I have tested it on MSVC8 and it works fine. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) namespace contract { namespace aux { template<typename Concept, typename Result> struct requires_msvc_result { typedef typename Result::type type; }; }} // namespace #define CONTRACT_AUX_CONCEPT_REQUIRES_MSVC_STRIP_PARENS_(x) x #define CONTRACT_AUX_CONCEPT_REQUIRES_MSVC_CHECK_(concept) \ ::boost::_requires_< void (*)(concept) > #define CONTRACT_AUX_CONCEPT_REQUIRES_MSVC_OPEN_TEMPLATE_(r, data, concept) \ ::contract::aux::requires_msvc_result< \ CONTRACT_AUX_CONCEPT_REQUIRES_MSVC_CHECK_ concept, #define CONTRACT_AUX_CONCEPT_REQUIRES_MSVC_CLOSE_TEMPLATE_(r, data, concept) > #define CONTRACT_AUX_CONCEPT_REQUIRES(concepts, result) \ typename BOOST_PP_SEQ_FOR_EACH( \ CONTRACT_AUX_CONCEPT_REQUIRES_MSVC_OPEN_TEMPLATE_, ~, concepts) \ ::boost::parameter::aux::unaryfunptr_arg_type<void (*) result> \ BOOST_PP_SEQ_FOR_EACH( \ CONTRACT_AUX_CONCEPT_REQUIRES_MSVC_CLOSE_TEMPLATE_, ~, \ concepts) \ ::type // No workaround needed -- use Boost.Concept implementation. #else // BOOST_WORKAROUND #define CONTRACT_AUX_CONCEPT_REQUIRES(concepts, result) \ BOOST_CONCEPT_REQUIRES(concepts, result) #endif // BOOST_WORKAROUND #endif // #include guard -- Lorenzo
participants (6)
-
Dave Abrahams
-
David Abrahams
-
Lorenzo Caminiti
-
Stefan van Kessel
-
Stephan T. Lavavej
-
Tim Moore