[GiNaC-devel] [PATCH] Fix compilation failure due to (template) operator- defined in factor.cpp

Alexei Sheplyakov varg at metalica.kh.ua
Mon Feb 23 13:03:16 CET 2009


GiNaC 1.5.0 fails to compile with g++ 3.4:

/bin/bash ../libtool --tag=CXX   --mode=compile ccache g++-3.4 -DHAVE_CONFIG_H -I. -I../../../../work/sw/GiNaC/ginac -I../config   -I/home/pc7135/varg/target/x86_64-linux-gnu/include    -Wall -O2 -g -pipe -funroll-loops -ffast-math -finline-limit=1200 -m64 -march=k8 -mfpmath=sse -msse2 -MT factor.lo -MD -MP -MF .deps/factor.Tpo -c -o factor.lo ../../../../work/sw/GiNaC/ginac/factor.cpp
libtool: compile:  ccache g++-3.4 -DHAVE_CONFIG_H -I. -I../../../../work/sw/GiNaC/ginac -I../config -I/home/pc7135/varg/target/x86_64-linux-gnu/include -Wall -O2 -g -pipe -funroll-loops -ffast-math -finline-limit=1200 -m64 -march=k8 -mfpmath=sse -msse2 -MT factor.lo -MD -MP -MF .deps/factor.Tpo -c ../../../../work/sw/GiNaC/ginac/factor.cpp  -fPIC -DPIC -o .libs/factor.o
../../../../work/sw/GiNaC/ginac/factor.cpp: In function `unsigned int GiNaC::unnamed::next_prime(unsigned int)':
../../../../work/sw/GiNaC/ginac/factor.cpp:1330: warning: converting of negative value `-0x00000000000000001' to `size_t'
stl_vector.h: In member function `size_t vector<GiNaC::unnamed::EvalPoint>::size() const':
stl_vector.h:375: error: ambiguous overload for 'operator-' in '((const vector<GiNaC::unnamed::GiNaC::unnamed::EvalPoint> *)this)->vector<GiNaC::unnamed::GiNaC::unnamed::EvalPoint>::end() - ((const vector<GiNaC::unnamed::EvalPoint> *)this)->vector<GiNaC::unnamed::EvalPoint>::begin()'
stl_iterator.h:759: note: candidates are: typename const_iter::difference_type operator-(const const_iter &, const const_iter &)
../../../../work/sw/GiNaC/ginac/factor.cpp:254: note: const_iter GiNaC::unnamed::operator-(const const_iter &, const const_iter &)
stl_deque.h:825: error: ambiguous overload for 'operator-' in '((const _Deque_base<GiNaC::unnamed::ModFactors> *)((const deque<GiNaC::unnamed::ModFactors> *)this))->_Deque_base<GiNaC::unnamed::ModFactors>::_M_impl._Deque_base<GiNaC::unnamed::ModFactors>::_Deque_impl::_M_finish - ((const _Deque_base<GiNaC::unnamed::ModFactors> *)((const deque<GiNaC::unnamed::ModFactors> *)this))->_Deque_base<GiNaC::unnamed::ModFactors>::_M_impl._Deque_base<GiNaC::unnamed::ModFactors>::_Deque_impl::_M_start'
stl_deque.h: In member function `size_t deque<GiNaC::unnamed::ModFactors>::size() const':
../../../../work/sw/GiNaC/ginac/factor.cpp:1534:   instantiated from here
stl_deque.h:671:   instantiated from `deque<GiNaC::unnamed::ModFactors>::deque(const deque<GiNaC::unnamed::ModFactors> &)'
../../../../work/sw/GiNaC/ginac/factor.cpp:1534:   instantiated from here
../../../../work/sw/GiNaC/ginac/factor.cpp:254: note: iter GiNaC::unnamed::operator-(const iter &, const iter &)
../../../../work/sw/GiNaC/ginac/container.h:375: error: ambiguous overload for 'operator-' in 'last - first'
../../../../work/sw/GiNaC/ginac/container.h: In member function `void GiNaC::container< <template-parameter-1-1> >::read_archive(const GiNaC::archive_node &, GiNaC::lst &)':
../../../../work/sw/GiNaC/ginac/factor.cpp:2586:   instantiated from here
../../../../work/sw/GiNaC/ginac/factor.cpp:2586:   instantiated from here
stl_iterator.h:759: note: typename const_iter::difference_type operator-(const const_iter &, const const_iter &)
../../../../work/sw/GiNaC/ginac/container.h:375: error: ambiguous overload for 'operator-' in 'last - first'
../../../../work/sw/GiNaC/ginac/container.h: In member function `void GiNaC::container< <template-parameter-1-1> >::read_archive(const GiNaC::archive_node &, GiNaC::lst &)':
../../../../work/sw/GiNaC/ginac/factor.cpp:2586:   instantiated from here
../../../../work/sw/GiNaC/ginac/factor.cpp:2586:   instantiated from here
stl_iterator.h:759: note: typename const_iter::difference_type operator-(const const_iter &, const const_iter &)

The following (silly) code makes the problem easier to analyze:

namespace N1
{
template<typename T1, typename T2> struct A
{
	T1 val;
	typedef T2 diff_t;
	explicit A(const T1& t) : val(t) { }
};

template<typename T>
typename T::diff_t operator-(const T& x, const T& y)
{
	typedef typename T::diff_t diff_t;
	return diff_t(x.val - y.val);
}

} // namespace N1

namespace N2
{

template<typename T> T operator-(const T& x, const T& y)
{
	return T(x.val - y.val);
}

int f()
{
	::N1::A<int, long> a(1), b(1);
	return (a - b).val;
	// ill-formed: both
	// N1::A N2::operator-(const N1::A&, const N1::A&)
	// and
	// N1::A::diff_t N1::operator-(const N1::A&, const N1::A&)
	// match.
}
} // namespace N2

The fix is simple: declare (and define) operator- (and operator+) only
for (univariate) polynomials.
---
 ginac/factor.cpp |   32 ++++++++++++++++++++++++++++++--
 1 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/ginac/factor.cpp b/ginac/factor.cpp
index b8a1fb8..2f9157b 100644
--- a/ginac/factor.cpp
+++ b/ginac/factor.cpp
@@ -218,8 +218,32 @@ static void expt_pos(umodpoly& a, unsigned int q)
 	}
 }
 
+template<bool COND, typename T = void> struct enable_if
+{
+	typedef T type;
+};
+
+template<typename T> struct enable_if<false, T> { /* empty */ };
+
+template<typename T> struct uvar_poly_p
+{
+	static const bool value = false;
+};
+
+template<> struct uvar_poly_p<upoly>
+{
+	static const bool value = true;
+};
+
+template<> struct uvar_poly_p<umodpoly>
+{
+	static const bool value = true;
+};
+
 template<typename T>
-static T operator+(const T& a, const T& b)
+// Don't define this for anything but univariate polynomials.
+static typename enable_if<uvar_poly_p<T>::value, T>::type
+operator+(const T& a, const T& b)
 {
 	int sa = a.size();
 	int sb = b.size();
@@ -250,7 +274,11 @@ static T operator+(const T& a, const T& b)
 }
 
 template<typename T>
-static T operator-(const T& a, const T& b)
+// Don't define this for anything but univariate polynomials. Otherwise
+// overload resolution might fail (this actually happens when compiling
+// GiNaC with g++ 3.4).
+static typename enable_if<uvar_poly_p<T>::value, T>::type
+operator-(const T& a, const T& b)
 {
 	int sa = a.size();
 	int sb = b.size();
-- 
1.5.6.5

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: Digital signature
URL: <http://www.cebix.net/pipermail/ginac-devel/attachments/20090223/81df6151/attachment.sig>


More information about the GiNaC-devel mailing list