[PATCH] Fix compilation failure due to (template) operator- defined in factor.cpp
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
participants (1)
-
Alexei Sheplyakov