[C++] SFINAE with MSVC 7.1
Does SFINAE work properly with MSVC++ 7.1 (2003)?
I'm having trouble getting boost::enable_if to work.
Yes it does, remember enable_if takes an "integral constant" in the Boost.MPL sense (metadata), enable_if_c takes a plain old boolean constant. Show us how you are trying to use it.
This is how I'm using it so far:
Now, it compiles fine when I create a matrix with rows == columns, but fails to compile when I try to instantiate one where rows != columns. I'm not attempting to call setIdentity() in either case.
Edit:
The error the compiler gives me is:
error C2039: 'type' : is not a member of 'boost::enable_if<Cond>'
with [ Cond=is_equal<2,3> ]
Just FYI, I'm trying to learn how to use SFINAE, I'm not trying to create a matrix class.
template < unsigned int v1, unsigned int v2>struct is_equal { const static bool value = false; };template < unsigned int v1 >struct is_equal <v1,v1> { const static bool value = true; };template < unsigned int rows, unsigned int columns>class matrix{public: typename boost::enable_if< is_equal<rows,columns> >::type setIdentity();};
Now, it compiles fine when I create a matrix with rows == columns, but fails to compile when I try to instantiate one where rows != columns. I'm not attempting to call setIdentity() in either case.
Edit:
The error the compiler gives me is:
error C2039: 'type' : is not a member of 'boost::enable_if<Cond>'
with [ Cond=is_equal<2,3> ]
Just FYI, I'm trying to learn how to use SFINAE, I'm not trying to create a matrix class.
Perhaps
class matrix{ void setIdentity(typename boost::enable_if<is_equal<rows,columns>::type>::type* dummy = 0);};
SFINAE trick works with overloads of template functions, you're using it on a non-template function which isn't correct regardless of it being inside of a class template.
Ah, ok. Thanks.
Is there a way to do what I'm trying to without partially specialising the class template? I'm trying to avoid partial specialisation because you have to repeat the entire class declaration.
Is there a way to do what I'm trying to without partially specialising the class template? I'm trying to avoid partial specialisation because you have to repeat the entire class declaration.
Quote:Original post by Nitage
Is there a way to do what I'm trying to without partially specialising the class template? I'm trying to avoid partial specialisation because you have to repeat the entire class declaration.
There are a thew ways you could go about this, one of the top of my head would be:
#include <cstddef>#include <boost/mpl/empty_base.hpp>#include <boost/mpl/equal_to.hpp>#include <boost/mpl/if.hpp>#include <boost/mpl/empty_base.hpp>#include <boost/mpl/size_t.hpp>namespace mpl = boost::mpl;template < typename Matrix >struct matrix_impl { typedef Matrix matrix_type; void setIdentity() { matrix_type& m = static_cast<matrix_type&>(*this); // do identity operation for(typename matrix_type::size_type i = 0; i < matrix_type::rows; ++i) for(typename matrix_type::size_type j = 0; j < matrix_type::columns; ++j) m[j] = ....; }};template < std::size_t rows_, std::size_t columns_ >struct matrix : public mpl::if_< mpl::equal_to< mpl::size_t<rows_>, mpl::size_t<columns_> >, matrix_impl< matrix<rows_, columns_> >, mpl::empty_base >::type { typedef float (&array_ref)[columns_]; typedef const float (&const_array_ref)[columns_]; typedef std::size_t size_type; static const std::size_t rows = rows_; static const std::size_t columns = columns_;private: float n[rows][columns];public: const_array_ref operator[](std::size_t n) const { return n[n]; } array_ref operator[](std::size_t n) { return n[n]; }};
Another way you could do it still using enable_if, you just make setIdentity a template function either a free-function or a static class member function.
The perhaps easiest way would be to use a static_assert in your setIdentity member function, as Jonathan Turkanis did with the move_ptr library in the operator*, operator-> and operator[].
Quote:Original post by dalleboy
The perhaps easiest way would be to use a static_assert in your setIdentity member function.
I use static asserts and/or Concept checking pretty much all the time with template code:
#include <cstddef>#include <boost/mpl/assert.hpp>#include <boost/mpl/equal_to.hpp>#include <boost/mpl/size_t.hpp>namespace mpl = boost::mpl;template < std::size_t M, std::size_t N >struct matrix { // ..... void setIdentity() { BOOST_MPL_ASSERT(( mpl::equal_to< mpl::size_t<M>, mpl::size_t<N> > )); // .... do set identity }};
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement