[C++] SFINAE with MSVC 7.1

Started by
7 comments, last by snk_kid 18 years, 1 month ago
Does SFINAE work properly with MSVC++ 7.1 (2003)? I'm having trouble getting boost::enable_if to work.
Advertisement
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:

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);};
Arguing on the internet is like running in the Special Olympics: Even if you win, you're still retarded.[How To Ask Questions|STL Programmer's Guide|Bjarne FAQ|C++ FAQ Lite|C++ Reference|MSDN]
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.
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[].
Arguing on the internet is like running in the Special Olympics: Even if you win, you're still retarded.[How To Ask Questions|STL Programmer's Guide|Bjarne FAQ|C++ FAQ Lite|C++ Reference|MSDN]
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