Sign in to follow this  
Nitage

[C++] SFINAE with MSVC 7.1

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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[i][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.

Share this post


Link to post
Share on other sites
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
}
};

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this