FIX work around VC7.1 and 8.0 problems with function template ambiguity

- use a lot of class template partial specialistion to help 'simplify' the template arguments
This commit is contained in:
Michael Stevens 2005-06-29 20:31:29 +00:00
parent c5a127d986
commit 5be4c2382a
3 changed files with 244 additions and 11 deletions

View File

@ -35,22 +35,25 @@
// Microsoft Visual C++
#if defined (BOOST_MSVC) && ! defined (BOOST_STRICT_CONFIG)
// Version 6.0 & 7.0
// Version 6.0 and 7.0
#if BOOST_MSVC <= 1300
#define BOOST_UBLAS_UNSUPPORTED_COMPILER
#endif
// Version 7.1
#if BOOST_MSVC == 1310
// Seeming still some problems with function templates
#define BOOST_UBLAS_MSVC71_FUNCTION_TEMPLATE_ORDERING
// One of these workarounds is needed for MSVC 7.1 AFAIK
// (thanks to John Maddock and Martin Lauer).
#if !(defined(BOOST_UBLAS_NO_NESTED_CLASS_RELATION) || defined(BOOST_UBLAS_MSVC_NESTED_CLASS_RELATION))
#define BOOST_UBLAS_NO_NESTED_CLASS_RELATION
#endif
// Version 7.1 and 8.0
#if BOOST_MSVC <= 1400
// Seeming still some problems with function templates
#define BOOST_UBLAS_MSVC_FUNCTION_TEMPLATE_ORDERING
#endif
#endif
#endif

View File

@ -3149,6 +3149,9 @@ namespace boost { namespace numeric { namespace ublas {
typename matrix_range<M>::matrix_type matrix_range<M>::nil_;
// Projections
#ifndef BOOST_UBLAS_MSVC_FUNCTION_TEMPLATE_ORDERING
// ISSUE MSVC cannot disambiguate the second function template argument
// - to work around this we define the project functions later using some helper classes
template<class M>
BOOST_UBLAS_INLINE
matrix_range<M> project (M &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
@ -3170,8 +3173,9 @@ namespace boost { namespace numeric { namespace ublas {
const matrix_range<M> project (const matrix_range<M> &data, const typename matrix_range<M>::range_type &r1, const typename matrix_range<M>::range_type &r2) {
return data.project (r1, r2);
}
#endif
// Specialize temporary
// Specialization of temporary_traits
template <class M>
struct matrix_temporary_traits< matrix_range<M> >
: matrix_temporary_traits< M > {} ;
@ -4045,6 +4049,7 @@ namespace boost { namespace numeric { namespace ublas {
typename matrix_slice<M>::matrix_type matrix_slice<M>::nil_;
// Projections
#ifndef BOOST_UBLAS_MSVC_FUNCTION_TEMPLATE_ORDERING
template<class M>
BOOST_UBLAS_INLINE
matrix_slice<M> project (M &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
@ -4056,7 +4061,6 @@ namespace boost { namespace numeric { namespace ublas {
// ISSUE was: return matrix_slice<M> (const_cast<M &> (data), s1, s2);
return matrix_slice<const M> (data, s1, s2);
}
#ifndef BOOST_UBLAS_MSVC71_FUNCTION_TEMPLATE_ORDERING
template<class M>
BOOST_UBLAS_INLINE
matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_slice<M>::range_type &r1, const typename matrix_slice<M>::range_type &r2) {
@ -4067,7 +4071,6 @@ namespace boost { namespace numeric { namespace ublas {
const matrix_slice<M> project (const matrix_slice<M> &data, const typename matrix_slice<M>::range_type &r1, const typename matrix_slice<M>::range_type &r2) {
return data.project (r1, r2);
}
#endif
template<class M>
BOOST_UBLAS_INLINE
matrix_slice<M> project (matrix_slice<M> &data, const typename matrix_slice<M>::slice_type &s1, const typename matrix_slice<M>::slice_type &s2) {
@ -4079,7 +4082,119 @@ namespace boost { namespace numeric { namespace ublas {
return data.project (s1, s2);
}
/// Specialization of temporary_traits
#else
// ISSUE MSVC cannot disambiguate the second function template argument
// - to work around this using some helper classes
namespace {
template <class M>
struct msvc_mproject_helper
{
typedef typename matrix_range<M>::range_type range_type;
typedef typename matrix_slice<M>::slice_type slice_type;
template <class RS>
struct return_type {
};
template <>
struct return_type<range_type> {
typedef matrix_range<M> type;
};
template <>
struct return_type<slice_type> {
typedef matrix_slice<M> type;
};
BOOST_UBLAS_INLINE
static matrix_range<M> apply (M &data, const range_type &r1, const range_type &r2) {
return matrix_range<M> (data, r1, r2);
}
BOOST_UBLAS_INLINE
static const matrix_range<M> apply (const M &data, const range_type &r1, const range_type &r2) {
return matrix_range<M> (data, r1, r2);
}
BOOST_UBLAS_INLINE
static matrix_slice<M> apply (M &data, const slice_type &s1, const slice_type &s2) {
return matrix_slice<M> (data, s1, s2);
}
BOOST_UBLAS_INLINE
static const matrix_slice<M> apply (const M &data, const slice_type &s1, const slice_type &s2) {
return const matrix_slice<M> (data, s1, s2);
}
};
template <class M>
struct msvc_mproject_helper< matrix_range<M> >
{
typedef typename matrix_range<M> base_type;
typedef typename matrix_range<M>::range_type range_type;
typedef typename matrix_slice<M>::slice_type slice_type;
template <class RS>
struct return_type {
};
template <>
struct return_type<range_type> {
typedef matrix_range<M> type;
};
template <>
struct return_type<slice_type> {
typedef matrix_slice<base_type> type; // no special proxy created for a slice of a range
};
BOOST_UBLAS_INLINE
static base_type apply (base_type &data, const range_type &r1, const range_type &r2) {
return data.project (r1, r2);
}
BOOST_UBLAS_INLINE
static const base_type apply (const base_type &data, const range_type &r1, const range_type &r) {
return data.project (r1, r2);
}
BOOST_UBLAS_INLINE
static matrix_slice<base_type> apply (base_type &data, const slice_type &s1, const slice_type &s2) {
return matrix_slice<base_type> (data, s1, s2);
}
BOOST_UBLAS_INLINE
static const matrix_slice<base_type> apply (const base_type &data, const slice_type &s1, const slice_type &s2) {
return const matrix_slice<const base_type> (data, s1, s2);
}
};
template <class M>
struct msvc_mproject_helper< matrix_slice<M> >
{
typedef typename matrix_slice<M> base_type;
typedef typename matrix_slice<M>::range_type range_type;
typedef typename matrix_slice<M>::slice_type slice_type;
template <class RS>
struct return_type {
typedef matrix_slice<M> type;
};
BOOST_UBLAS_INLINE
static matrix_slice<M> apply (base_type &data, const range_type &r1, const range_type &r2) {
return data.project (r1, r2);
}
BOOST_UBLAS_INLINE
static const matrix_slice<M> apply (const base_type &data, const range_type &r1, const range_type &r2) {
return data.project (r1, r2);
}
BOOST_UBLAS_INLINE
static matrix_slice<M> apply (base_type &data, const slice_type &s1, const slice_type &s2) {
return data.project (s1, s2);
}
BOOST_UBLAS_INLINE
static const matrix_slice<M> apply (const base_type &data, const slice_type &s1, const slice_type &s2) {
return data.project (s1, s2);
}
};
}
template<class M, class RS>
BOOST_UBLAS_INLINE
typename msvc_mproject_helper<M>::template return_type<RS>::type project (M &data, const RS &rs1, const RS &rs2) {
return msvc_mproject_helper<M>::apply (data, rs1, rs2);
}
template<class M, class RS>
BOOST_UBLAS_INLINE
const typename msvc_mproject_helper<M>::template return_type<RS>::type project (const M &data, const RS &rs1, const RS &rs2) {
return msvc_mproject_helper<const M>::apply (data, rs1, rs2);
}
#endif
// Specialization of temporary_traits
template <class M>
struct matrix_temporary_traits< matrix_slice<M> >
: matrix_temporary_traits< M > {};

View File

@ -479,14 +479,17 @@ namespace boost { namespace numeric { namespace ublas {
typename vector_range<V>::vector_type vector_range<V>::nil_;
// Projections
#ifndef BOOST_UBLAS_MSVC_FUNCTION_TEMPLATE_ORDERING
// ISSUE MSVC cannot disambiguate the second function template argument
// - to work around this we define the project functions later using some helper classes
template<class V>
BOOST_UBLAS_INLINE
vector_range<V> project (V &data, const typename vector_range<V>::range_type &r) {
vector_range<V> project (V &data, typename vector_range<V>::range_type const &r) {
return vector_range<V> (data, r);
}
template<class V>
BOOST_UBLAS_INLINE
const vector_range<const V> project (const V &data, const typename vector_range<V>::range_type &r) {
const vector_range<const V> project (const V &data, typename vector_range<V>::range_type const &r) {
// ISSUE was: return vector_range<V> (const_cast<V &> (data), r);
return vector_range<const V> (data, r);
}
@ -500,6 +503,7 @@ namespace boost { namespace numeric { namespace ublas {
const vector_range<V> project (const vector_range<V> &data, const typename vector_range<V>::range_type &r) {
return data.project (r);
}
#endif
// Specialization of temporary_traits
template <class V>
@ -969,6 +973,7 @@ namespace boost { namespace numeric { namespace ublas {
typename vector_slice<V>::vector_type vector_slice<V>::nil_;
// Projections
#ifndef BOOST_UBLAS_MSVC_FUNCTION_TEMPLATE_ORDERING
template<class V>
BOOST_UBLAS_INLINE
vector_slice<V> project (V &data, const typename vector_slice<V>::slice_type &s) {
@ -990,7 +995,6 @@ namespace boost { namespace numeric { namespace ublas {
const vector_slice<V> project (const vector_slice<V> &data, const typename vector_slice<V>::slice_type &s) {
return data.project (s);
}
#ifndef BOOST_UBLAS_MSVC71_FUNCTION_TEMPLATE_ORDERING
template<class V>
BOOST_UBLAS_INLINE
vector_slice<V> project (vector_slice<V> &data, const typename vector_slice<V>::range_type &r) {
@ -1001,6 +1005,117 @@ namespace boost { namespace numeric { namespace ublas {
const vector_slice<V> project (const vector_slice<V> &data, const typename vector_slice<V>::range_type &r) {
return data.project (r);
}
#else
// ISSUE MSVC cannot disambiguate the second function template argument
// - to work around this using some helper classes
namespace {
template <class V>
struct msvc_vproject_helper
{
typedef typename vector_range<V>::range_type range_type;
typedef typename vector_slice<V>::slice_type slice_type;
template <class RS>
struct return_type {
};
template <>
struct return_type<range_type> {
typedef vector_range<V> type;
};
template <>
struct return_type<slice_type> {
typedef vector_slice<V> type;
};
BOOST_UBLAS_INLINE
static vector_range<V> apply (V &data, const range_type &r) {
return vector_range<V> (data, r);
}
BOOST_UBLAS_INLINE
static const vector_range<V> apply (const V &data, const range_type &r) {
return vector_range<V> (data, r);
}
BOOST_UBLAS_INLINE
static vector_slice<V> apply (V &data, const slice_type &s) {
return vector_slice<V> (data, s);
}
BOOST_UBLAS_INLINE
static const vector_slice<V> apply (const V &data, const slice_type &s) {
return const vector_slice<V> (data, s);
}
};
template <class V>
struct msvc_vproject_helper< vector_range<V> >
{
typedef typename vector_range<V> base_type;
typedef typename vector_range<V>::range_type range_type;
typedef typename vector_slice<V>::slice_type slice_type;
template <class RS>
struct return_type {
};
template <>
struct return_type<range_type> {
typedef vector_range<V> type;
};
template <>
struct return_type<slice_type> {
typedef vector_slice<base_type> type; // no special proxy created for a slice of a range
};
BOOST_UBLAS_INLINE
static base_type apply (base_type &data, const range_type &r) {
return data.project (r);
}
BOOST_UBLAS_INLINE
static const base_type apply (const base_type &data, const range_type &r) {
return data.project (r);
}
BOOST_UBLAS_INLINE
static vector_slice<base_type> apply (base_type &data, const slice_type &s) {
return vector_slice<base_type> (data, s);
}
BOOST_UBLAS_INLINE
static const vector_slice<base_type> apply (const base_type &data, const slice_type &s) {
return const vector_slice<const base_type> (data, s);
}
};
template <class V>
struct msvc_vproject_helper< vector_slice<V> >
{
typedef typename vector_slice<V> base_type;
typedef typename vector_slice<V>::range_type range_type;
typedef typename vector_slice<V>::slice_type slice_type;
template <class RS>
struct return_type {
typedef vector_slice<V> type;
};
BOOST_UBLAS_INLINE
static vector_slice<V> apply (base_type &data, const range_type &r) {
return data.project (r);
}
BOOST_UBLAS_INLINE
static const vector_slice<V> apply (const base_type &data, const range_type &r) {
return data.project (r);
}
BOOST_UBLAS_INLINE
static vector_slice<V> apply (base_type &data, const slice_type &s) {
return data.project (s);
}
BOOST_UBLAS_INLINE
static const vector_slice<V> apply (const base_type &data, const slice_type &s) {
return data.project (s);
}
};
}
template<class V, class RS>
BOOST_UBLAS_INLINE
typename msvc_vproject_helper<V>::template return_type<RS>::type project (V &data, const RS &rs) {
return msvc_vproject_helper<V>::apply (data, rs);
}
template<class V, class RS>
BOOST_UBLAS_INLINE
const typename msvc_vproject_helper<V>::template return_type<RS>::type project (const V &data, const RS &rs) {
return msvc_vproject_helper<const V>::apply (data, rs);
}
#endif
// Specialization of temporary_traits