marten_range, which do you think is better to use, boost concept checks or boost::is_integral<>? What would be the advantages of one over the other?
Printable View
marten_range, which do you think is better to use, boost concept checks or boost::is_integral<>? What would be the advantages of one over the other?
In the past I have been using BOOST_STATIC_ASSERT and boost type-traits (such as boost::is_intergral<>) to enforce concepts and only recently began using boost concepts library.Quote:
Originally Posted by HighCommander4
BOOST_STATIC_ASSERT worked very well for me but I think boost concept library is a more complete solution.
One advantage of using boost concept library is that the boost community jumped through some rings in order to provide portable and easy to understand compile-time errors when concepts are violated. As the presentation of compile-time errors are not mandated by the standard it's difficult to get consistent concept error reportage across compilers.
Hope this helps
Just to add to what marten said.
In this case, concept checks and type_traits work in exactly the same way (More or less), so the difference is not that great, though concept checks may result in slightly more readable code and error messages (IMO).
The point where concept checks really stand out (Again IMO), is when you for instance use them to limit the types of iterators a template function can take. Just to give you an example: (Code from a Unicode library I'm currently writing)This function composes the hangul sequence [first, last] and outputs the results through 'out'. By using concepts checks here the user is now unable to for instance pass a std::istream_iterator<int> as 'wi_iter', since that iterator isn't writable. If you tried that, the compiler would give a nice error message (Most of the time anyway) that a Writable iterator is required, instead of spitting a cryptic message from the depths of the library where you eventually write to the thing.Code:template<typename rs_iter, typename wi_iter>
void compose_hangul(rs_iter first, const rs_iter& last, wi_iter out)
{
// Concept checking of template parameters:
function_requires<boost_concepts::ReadableIteratorConcept<rs_iter> >();
function_requires<boost_concepts::SinglePassIteratorConcept<rs_iter> >();
function_requires<boost_concepts::WritableIteratorConcept<wi_iter, code_point_type> >();
function_requires<boost_concepts::IncrementableIteratorConcept<wi_iter> >();
<boring details removed>
}
Needless to say, I love these things.. :)
Thanks Wien. That's very helpful.
Kheun,
You are going to like this. It's a way to restrict the compiler from finding a match for a function unless a given condition is true.
In order for the compiler to match the 3rd argument, it must use the true restrict_to template specialization. If the condition is false, type doesn't exist as so the compiler can't find a valid instantiation for the template function.Code:template <bool> struct restrict_to {};
template <> struct restrict_to<true> {typedef void* type};
#define RESTRICT_TO(condition) \
typename restrict_to<condition>::type = 0
template <typename IntType>
IntType Add(IntType x, IntType y, RESTRICT_TO(boost::is_integral<IntType>::value))
{
return x+y;
}
The only down side is that an extra parameter is passed into the function. But being a template and that it will usually be inlined, the compiler will normally optimize this away. But in certain circumstances it will not be able to do so.
Anyway, I hope you enjoy this technique -- or at least reading about it. :)
Thanks, Kevin. I'll try it out.