Hi
Med builds are failing with
medfile_int_wrap.cc:11272:30: error: no matching function for call to 'std::vector<double, std::allocator<double> >::erase(SwigValueWrapper<__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >&)' result = (arg1)->erase(arg2);
A standalone version which fails to compile (ignoring the fact that arg2 is not initialized):
---------------------
#include <vector>
typedef double med_float;
template<typename T> class SwigValueWrapper { struct SwigMovePointer { T *ptr; SwigMovePointer(T *p) : ptr(p) { } ~SwigMovePointer() { delete ptr; } SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } } pointer; SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs); SwigValueWrapper(const SwigValueWrapper<T>& rhs); public: SwigValueWrapper() : pointer(0) { } SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } operator T&() const { return *pointer.ptr; } T *operator&() { return pointer.ptr; } };
template <typename T> T SwigValueInit() { return T(); }
int main() { std::vector< med_float > arg1; SwigValueWrapper< std::vector< double >::iterator > arg2; arg1.erase(arg2); };
---------------------
GCC 5 compiles the code. GCC6 seems to require an explicit cast, even though
std::vector<double>::iterator it = arg2;
works. GCC bug?
Thanks asndro
On Thu, Feb 04, 2016 at 01:36:50PM +0100, Sandro Mani wrote:
Med builds are failing with
medfile_int_wrap.cc:11272:30: error: no matching function for call to 'std::vector<double, std::allocator<double> >::erase(SwigValueWrapper<__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >&)' result = (arg1)->erase(arg2);
A standalone version which fails to compile (ignoring the fact that arg2 is not initialized):
GCC 5 compiles the code. GCC6 seems to require an explicit cast, even though
std::vector<double>::iterator it = arg2;
works. GCC bug?
GCC 5 fails the same way if you compile with -std=c++11 or -std=c++14, the latter is the default for GCC 6.
Jakub
On 04.02.2016 13:40, Jakub Jelinek wrote:
On Thu, Feb 04, 2016 at 01:36:50PM +0100, Sandro Mani wrote:
Med builds are failing with
medfile_int_wrap.cc:11272:30: error: no matching function for call to 'std::vector<double, std::allocator<double> >::erase(SwigValueWrapper<__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >&)' result = (arg1)->erase(arg2);
A standalone version which fails to compile (ignoring the fact that arg2 is not initialized):
GCC 5 compiles the code. GCC6 seems to require an explicit cast, even though
std::vector<double>::iterator it = arg2;
works. GCC bug?
GCC 5 fails the same way if you compile with -std=c++11 or -std=c++14, the latter is the default for GCC 6.
So in short, an explicit cast is needed?
On 04/02/16 13:44 +0100, Sandro Mani wrote:
On 04.02.2016 13:40, Jakub Jelinek wrote:
On Thu, Feb 04, 2016 at 01:36:50PM +0100, Sandro Mani wrote:
Med builds are failing with
medfile_int_wrap.cc:11272:30: error: no matching function for call to 'std::vector<double, std::allocator<double> >::erase(SwigValueWrapper<__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >&)' result = (arg1)->erase(arg2);
A standalone version which fails to compile (ignoring the fact that arg2 is not initialized):
GCC 5 compiles the code. GCC6 seems to require an explicit cast, even though
std::vector<double>::iterator it = arg2;
works. GCC bug?
GCC 5 fails the same way if you compile with -std=c++11 or -std=c++14, the latter is the default for GCC 6.
So in short, an explicit cast is needed?
Yes, with an explicit cast to vector<T>::iterator the code is valid in C++03 and C++11. For the C++11 case only one implicit conversion will be needed to get a const_iterator, so it will compile.
On 04/02/16 13:36 +0100, Sandro Mani wrote:
Hi
Med builds are failing with
medfile_int_wrap.cc:11272:30: error: no matching function for call to 'std::vector<double, std::allocator<double> >::erase(SwigValueWrapper<__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > > >&)' result = (arg1)->erase(arg2);
A standalone version which fails to compile (ignoring the fact that arg2 is not initialized):
#include <vector>
typedef double med_float;
template<typename T> class SwigValueWrapper { struct SwigMovePointer { T *ptr; SwigMovePointer(T *p) : ptr(p) { } ~SwigMovePointer() { delete ptr; } SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } } pointer; SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs); SwigValueWrapper(const SwigValueWrapper<T>& rhs); public: SwigValueWrapper() : pointer(0) { } SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } operator T&() const { return *pointer.ptr; } T *operator&() { return pointer.ptr; } };
template <typename T> T SwigValueInit() { return T(); }
int main() { std::vector< med_float > arg1; SwigValueWrapper< std::vector< double >::iterator > arg2; arg1.erase(arg2); };
GCC 5 compiles the code. GCC6 seems to require an explicit cast, even though
std::vector<double>::iterator it = arg2;
works. GCC bug?
No. As explained at https://gcc.gnu.org/gcc-6/porting_to.html the default -std option is different in GCC 6. This code fails with GCC 5 as well if you use -std=c++11, so it's obviously a C++98 vs C++11 difference, not a GCC 5 vs GCC 6 difference.
In C++11 std::vector<T>::erase() takes a const_iterator not iterator. The SwigValueWrapper only converts to vector::iterator, so the call to erase() would require two user-defined conversions (one to iterator and another one to const_iterator) which is forbidden by the language.
On 04.02.2016 13:45, Jonathan Wakely wrote:
On 04/02/16 13:36 +0100, Sandro Mani wrote:
Hi
Med builds are failing with
medfile_int_wrap.cc:11272:30: error: no matching function for call to 'std::vector<double, std::allocator<double>
::erase(SwigValueWrapper<__gnu_cxx::__normal_iterator<double*,
std::vector<double, std::allocator<double> > > >&)' result = (arg1)->erase(arg2);
A standalone version which fails to compile (ignoring the fact that arg2 is not initialized):
#include <vector>
typedef double med_float;
template<typename T> class SwigValueWrapper { struct SwigMovePointer { T *ptr; SwigMovePointer(T *p) : ptr(p) { } ~SwigMovePointer() { delete ptr; } SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } } pointer; SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs); SwigValueWrapper(const SwigValueWrapper<T>& rhs); public: SwigValueWrapper() : pointer(0) { } SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } operator T&() const { return *pointer.ptr; } T *operator&() { return pointer.ptr; } };
template <typename T> T SwigValueInit() { return T(); }
int main() { std::vector< med_float > arg1; SwigValueWrapper< std::vector< double >::iterator > arg2; arg1.erase(arg2); };
GCC 5 compiles the code. GCC6 seems to require an explicit cast, even though
std::vector<double>::iterator it = arg2;
works. GCC bug?
No. As explained at https://gcc.gnu.org/gcc-6/porting_to.html the default -std option is different in GCC 6. This code fails with GCC 5 as well if you use -std=c++11, so it's obviously a C++98 vs C++11 difference, not a GCC 5 vs GCC 6 difference.
In C++11 std::vector<T>::erase() takes a const_iterator not iterator. The SwigValueWrapper only converts to vector::iterator, so the call to erase() would require two user-defined conversions (one to iterator and another one to const_iterator) which is forbidden by the language.
Okay, looks like SWIG needs some updating. Thanks for the explanation.
devel@lists.stg.fedoraproject.org