Hi Peeps Can anyone cast any light on this... I want to write function which accepts a single pass range of X's, so something like this struct X { }; template <typename T> BOOST_CONCEPT_REQUIRES( (( boost::SinglePassRangeConcept<T> )), ( typename boost::enable_if<boost::is_same<typename boost::range_value<T>::type, X>, void>::type )) my_function( const T & range ); Is that a reasonable construction, or is there a better way to say it? Next, it doesn't seem to work. It does seem to work if the type to which enable_if resolves is anything except void, but not for void. Why is this? TIA - Rob.
On Tue, 27 Mar 2012, Robert Jones wrote:
Hi Peeps Can anyone cast any light on this...
I want to write function which accepts a single pass range of X's, so something like this
struct X { };
template <typename T> BOOST_CONCEPT_REQUIRES( (( boost::SinglePassRangeConcept<T> )), ( typename boost::enable_if<boost::is_same<typename boost::range_value<T>::type, X>, void>::type )) my_function( const T & range );
Is that a reasonable construction, or is there a better way to say it?
Next, it doesn't seem to work. It does seem to work if the type to which enable_if resolves is anything except void, but not for void. Why is this?
Does it only fail if you try to pass something in that is not a range? I'm not sure that BOOST_CONCEPT_REQUIRES does SFINAE, but if it does, you will need a metafunction (and possibly lazy_enable_if) to avoid accessing range_value<T> when T is not a range if that doesn't instantiate properly for non-ranges. -- Jeremiah Willcock
On Tue, 27 Mar 2012, Robert Jones wrote:
Hi Peeps
Can anyone cast any light on this...
I want to write function which accepts a single pass range of X's, so something like this
struct X { };
template <typename T> BOOST_CONCEPT_REQUIRES( (( boost::SinglePassRangeConcept<**T> )), ( typename boost::enable_if<boost::is_**same<typename boost::range_value<T>::type, X>, void>::type )) my_function( const T & range );
Is that a reasonable construction, or is there a better way to say it?
Next, it doesn't seem to work. It does seem to work if the type to which enable_if resolves is anything except void, but not for void. Why is this?
Does it only fail if you try to pass something in that is not a range? I'm not sure that BOOST_CONCEPT_REQUIRES does SFINAE, but if it does, you will need a metafunction (and possibly lazy_enable_if) to avoid accessing range_value<T> when T is not a range if that doesn't instantiate properly for non-ranges.
No, it fails when the parameter IS a valid range, of the required value type. I can create the same effect by substituting void for the whole enable_if bit, and then using BOOST_ASSERT in the body of the function to impose
On Tue, Mar 27, 2012 at 5:02 PM, Jeremiah Willcock <jewillco@osl.iu.edu>wrote: the same condition, but that is obviously less satisfactory. I suspect void is special because it is enable_if's returned type if type is not specified, but I can't quite see why, or what the impact of that is. Thx, Rob.
On Tue, 27 Mar 2012, Robert Jones wrote:
On Tue, Mar 27, 2012 at 5:02 PM, Jeremiah Willcock <jewillco@osl.iu.edu> wrote: On Tue, 27 Mar 2012, Robert Jones wrote:
Hi Peeps Can anyone cast any light on this...
I want to write function which accepts a single pass range of X's, so something like this
struct X { };
template <typename T> BOOST_CONCEPT_REQUIRES( (( boost::SinglePassRangeConcept<T> )), ( typename boost::enable_if<boost::is_same<typename boost::range_value<T>::type, X>, void>::type )) my_function( const T & range );
Is that a reasonable construction, or is there a better way to say it?
Next, it doesn't seem to work. It does seem to work if the type to which enable_if resolves is anything except void, but not for void. Why is this?
Does it only fail if you try to pass something in that is not a range? I'm not sure that BOOST_CONCEPT_REQUIRES does SFINAE, but if it does, you will need a metafunction (and possibly lazy_enable_if) to avoid accessing range_value<T> when T is not a range if that doesn't instantiate properly for non-ranges.
No, it fails when the parameter IS a valid range, of the required value type. I can create the same effect by substituting void for the whole enable_if bit, and then using BOOST_ASSERT in the body of the function to impose the same condition, but that is obviously less satisfactory.
I suspect void is special because it is enable_if's returned type if type is not specified, but I can't quite see why, or what the impact of that is.
Does it still fail even if you don't use BOOST_CONCEPT_REQUIRES? If the function fails only with a void return type, are you sure you're not trying to return something (at least along some control flow path)? What in particular is the error message you get? -- Jeremiah Willcock
On Tue, Mar 27, 2012 at 8:21 PM, Jeremiah Willcock <jewillco@osl.iu.edu>wrote:
On Tue, 27 Mar 2012, Robert Jones wrote:
On Tue, Mar 27, 2012 at 5:02 PM, Jeremiah Willcock <jewillco@osl.iu.edu>
wrote: On Tue, 27 Mar 2012, Robert Jones wrote:
Hi Peeps Can anyone cast any light on this...
I want to write function which accepts a single pass range of X's, so something like this
struct X { };
template <typename T> BOOST_CONCEPT_REQUIRES( (( boost::SinglePassRangeConcept<**T> )), ( typename boost::enable_if<boost::is_**same<typename boost::range_value<T>::type, X>, void>::type )) my_function( const T & range );
Is that a reasonable construction, or is there a better way to say it?
Next, it doesn't seem to work. It does seem to work if the type to which enable_if resolves is anything except void, but not for void. Why is this?
Does it only fail if you try to pass something in that is not a range? I'm not sure that BOOST_CONCEPT_REQUIRES does SFINAE, but if it does, you will need a metafunction (and possibly lazy_enable_if) to avoid accessing range_value<T> when T is not a range if that doesn't instantiate properly for non-ranges.
No, it fails when the parameter IS a valid range, of the required value type. I can create the same effect by substituting void for the whole enable_if bit, and then using BOOST_ASSERT in the body of the function to impose the same condition, but that is obviously less satisfactory.
I suspect void is special because it is enable_if's returned type if type is not specified, but I can't quite see why, or what the impact of that is.
Does it still fail even if you don't use BOOST_CONCEPT_REQUIRES? If the function fails only with a void return type, are you sure you're not trying to return something (at least along some control flow path)? What in particular is the error message you get?
No. I can use the enable_if part without the BOOST_CONCEPT_REQUIRES and it's fine. I can use the BOOST_CONCEPT_REQUIRES bit and then use a simple void in place of the enable_if and that's fine too. Together, not fine! I'm going to take a little time to construct a minimal self contained example. Thx, Rob.
Hi All Ok, I should probably have started this thread with this self contained code example. What's wrong with this? #include <vector> #include <boost/concept/requires.hpp> #include <boost/range/concepts.hpp> #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp> template <typename T> BOOST_CONCEPT_REQUIRES( (( boost::SinglePassRangeConcept<T> )), // ( void )) ( typename boost::enable_if<boost::is_same<typename boost::range_value<T>::type, int>, void>::type )) f( const T & ) { } int main( ) { std::vector<int> v; f( v ); } g++ -c -o enable_if.o enable_if.cpp enable_if.cpp: In function ‘int main()’: enable_if.cpp:17: error: no matching function for call to ‘f(std::vector<int, std::allocator<int> >&)’ If I comment out the enable_if line and comment in the void line it's fine. TIA, Rob.
On Wed, 28 Mar 2012, Robert Jones wrote:
Hi All
Ok, I should probably have started this thread with this self contained code example.
What's wrong with this?
#include <vector> #include <boost/concept/requires.hpp> #include <boost/range/concepts.hpp> #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp>
template <typename T> BOOST_CONCEPT_REQUIRES( (( boost::SinglePassRangeConcept<T> )), // ( void )) ( typename boost::enable_if<boost::is_same<typename boost::range_value<T>::type, int>, void>::type )) f( const T & ) { }
int main( ) { std::vector<int> v; f( v ); }
g++ -c -o enable_if.o enable_if.cpp enable_if.cpp: In function ‘int main()’: enable_if.cpp:17: error: no matching function for call to ‘f(std::vector<int, std::allocator<int> >&)’
If I comment out the enable_if line and comment in the void line it's fine.
It looks like the trick is to put the enable_if outside the BOOST_CONCEPT_REQUIRES, as in: template <typename T> typename enable_if< condition, BOOST_CONCEPT_REQUIRES(concept, (void))>::type Paragraph 4 of [dcl.fct] (in the latest draft) seems to say that the SFINAE error you are getting is required: only the specific type void, written in a non-dependent way, counts as a valid function parameter type. -- Jeremiah Willcock
On Wed, Mar 28, 2012 at 4:24 PM, Jeremiah Willcock <jewillco@osl.iu.edu>wrote:
It looks like the trick is to put the enable_if outside the BOOST_CONCEPT_REQUIRES, as in:
template <typename T> typename enable_if< condition, BOOST_CONCEPT_REQUIRES(**concept, (void))>::type
Paragraph 4 of [dcl.fct] (in the latest draft) seems to say that the SFINAE error you are getting is required: only the specific type void, written in a non-dependent way, counts as a valid function parameter type.
Well, I can't deny that it works! Seems to be reading quite a bit into the standard tho', assuming you're looking at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf If I'm reading it right it is actually talking about function parameter lists, rather than function return types, and stating that void is not a valid parameter type except for f(void) to indicate an empty parameter list. Thx, Rob.
On Wed, 28 Mar 2012, Robert Jones wrote:
On Wed, Mar 28, 2012 at 4:24 PM, Jeremiah Willcock <jewillco@osl.iu.edu> wrote:
It looks like the trick is to put the enable_if outside the BOOST_CONCEPT_REQUIRES, as in:
template <typename T> typename enable_if< condition, BOOST_CONCEPT_REQUIRES(concept, (void))>::type
Paragraph 4 of [dcl.fct] (in the latest draft) seems to say that the SFINAE error you are getting is required: only the specific type void, written in a non-dependent way, counts as a valid function parameter type.
Well, I can't deny that it works! Seems to be reading quite a bit into the standard tho', assuming you're looking at
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
If I'm reading it right it is actually talking about function parameter lists, rather than function return types, and stating that void is not a valid parameter type except for f(void) to indicate an empty parameter list.
The internals of BOOST_CONCEPT_REQUIRES take the type that you give as the return type and use it as a function parameter type (that is why you need the parentheses around the outside). That is where those rules in the standard get involved. -- Jeremiah Willcock
On Wed, Mar 28, 2012 at 6:09 PM, Jeremiah Willcock <jewillco@osl.iu.edu>wrote:
On Wed, 28 Mar 2012, Robert Jones wrote:
On Wed, Mar 28, 2012 at 4:24 PM, Jeremiah Willcock <jewillco@osl.iu.edu>
wrote:
It looks like the trick is to put the enable_if outside the BOOST_CONCEPT_REQUIRES, as in:
template <typename T> typename enable_if< condition, BOOST_CONCEPT_REQUIRES(**concept, (void))>::type
Paragraph 4 of [dcl.fct] (in the latest draft) seems to say that the SFINAE error you are getting is required: only the specific type void, written in a non-dependent way, counts as a valid function parameter type.
Well, I can't deny that it works! Seems to be reading quite a bit into the standard tho', assuming you're looking at
If I'm reading it right it is actually talking about function parameter lists, rather than function return types, and stating that void is not a valid parameter type except for f(void) to indicate an empty parameter list.
The internals of BOOST_CONCEPT_REQUIRES take the type that you give as the return type and use it as a function parameter type (that is why you need the parentheses around the outside). That is where those rules in the standard get involved.
Ah, thank you, clears it up nicely. I can sleep peacefully! - Rob.
on Tue Mar 27 2012, Jeremiah Willcock <jewillco-AT-osl.iu.edu> wrote:
On Tue, 27 Mar 2012, Robert Jones wrote:
Hi Peeps Can anyone cast any light on this...
I want to write function which accepts a single pass range of X's, so something like this
struct X { };
template <typename T> BOOST_CONCEPT_REQUIRES( (( boost::SinglePassRangeConcept<T> )), ( typename boost::enable_if<boost::is_same<typename boost::range_value<T>::type, X>, void>::type )) my_function( const T & range );
Is that a reasonable construction, or is there a better way to say it?
Next, it doesn't seem to work. It does seem to work if the type to which enable_if resolves is anything except void, but not for void. Why is this?
Does it only fail if you try to pass something in that is not a range? I'm not sure that BOOST_CONCEPT_REQUIRES does SFINAE, but if it does,
It doesn't. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (3)
-
Dave Abrahams
-
Jeremiah Willcock
-
Robert Jones