By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,305 Members | 1,614 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,305 IT Pros & Developers. It's quick & easy.

Problem with implicit conversion

P: n/a
Hello,

I have written a program that compiles just fine with GCC 3.3. With
GCC 3.4.1 it results in this error:

g++ -O0 -g3 -Wall -c -oTestp.o ../Testp.c
.../Testp.c: In function `int main()':
.../Testp.c:26: error: no match for 'operator<=' in 't <= 2.0e+0'

Please help me, I have no idea where the problem is.

Here is the code:

template <class T> class BasisF;

template <class T> inline bool operator<=(const BasisF<T> &a, const
BasisF<T> &b){return a.x <= b.x;}

template<class T> class BasisF{

public:
T x;
BasisF(const T &_x = T()): x(_x){}
BasisF(const BasisF &_b): x(_b.x){}
~BasisF(){}
BasisF& operator= (const T &_x){
x = _x;
return *this;
}
friend bool operator<=<>(const BasisF &a, const BasisF &b);
};

#define min(a,b) ((a) <= (b) ? (a) : (b))

int main(){
BasisF<double> t(1);
if (min(t,2.0)<=0) return 1;
return 0;
}

Regards,
Boris
Jul 22 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Boris wrote in news:41*************************@posting.google.co m in
comp.lang.c++:

I have written a program that compiles just fine with GCC 3.3. With
GCC 3.4.1 it results in this error:

g++ -O0 -g3 -Wall -c -oTestp.o ../Testp.c
../Testp.c: In function `int main()':
../Testp.c:26: error: no match for 'operator<=' in 't <= 2.0e+0'

Please help me, I have no idea where the problem is.


The problem is that double isn't an exact match for a deducable
paramiter:

template <class T> class BasisF;

/* Prevent the compiler from triing to deduce T from the second
argument, and force the conversion.
*/
template < typename T > struct identity { typedef T type; };

template <class T>
inline bool operator <= (
BasisF<T> const &a,
typename identity< BasisF<T> >::type const &b
)
{
return a.x <= b.x;
}

template<class T>
class BasisF
{
public:
T x;
BasisF( T const &_x = T() ) : x( _x) {}
BasisF(BasisF const &_b) : x( _b.x ) {}
~BasisF() {}
BasisF& operator= (T const &_x)
{
x = _x;
return *this;
}
};

#define min(a,b) ((a) <= (b) ? (a) : (b))

int main()
{
BasisF<double> t(1);

/* Note only 0, EXIT_SUCCESS and EXIT_FAILURE (both from <cstdlib>) are
standard (portable) return values for main().
*/
if (min(t,2.0)<=0) return 1;

return 0;
}

The problem with the above is 0.0 <= BaseF< double >( 0.0 ) doesn't work.

Here's a version that does:

template <class T> class BasisF;

/* Boilerplate
*/
template < typename Left, typename Right >
struct BasisF_comp_enable
{
};

template < typename T >
struct BasisF_comp_enable< BasisF< T >, BasisF< T > >
{
/* enable_if return type
*/
typedef bool bool_type;

/* actual type to compare
*/
typedef BasisF< T > comp_type;
};

/* Left handed version
*/
template < typename T >
struct BasisF_comp_enable< BasisF< T >, T >
{
typedef bool bool_type;
typedef BasisF< T > comp_type;
};

/* Rhight handed version
*/
template < typename T >
struct BasisF_comp_enable< T, BasisF< T > >
{
typedef bool bool_type;
typedef BasisF< T > comp_type;
};

template < typename Left, typename Right >
inline typename BasisF_comp_enable< Left, Right >::bool_type
operator <= ( Left const &left, Right const &right )
{
typedef typename BasisF_comp_enable< Left, Right >::comp_type type;

type const &lhs = left;
type const &rhs = right;

return lhs.x < rhs.x;
}

template<class T>
struct BasisF
{
T x;
BasisF( T const &_x = T() ) : x( _x) {}
};
#include <iostream>
#include <ostream>
#include <iomanip>

int main()
{
using namespace std;

BasisF<double> t(1);

cout << boolalpha << ( t <= 2.0 ) << '\n';
cout << boolalpha << ( 0.0 <= t ) << '\n';
}

There is a lot of boilerplate above, but you can presumably
reuse it for other operators, but check out the links bellow.

links:

http://boost-consulting.com/boost/li...enable_if.html

<http://groups.google.co.uk/groups?hl=en&lr=&ie=UTF-8
&q********************************************@met rowerks.com>

aka: http://tinyurl.com/5kh86

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #2

P: n/a
Boris wrote:
I have written a program that compiles just fine with GCC 3.3. With
GCC 3.4.1 it results in this error:

g++ -O0 -g3 -Wall -c -oTestp.o ../Testp.c
../Testp.c: In function `int main()':
../Testp.c:26: error: no match for 'operator<=' in 't <= 2.0e+0'

Please help me, I have no idea where the problem is.

Here is the code:

template <class T> class BasisF;

template <class T> inline bool operator<=(const BasisF<T> &a, const
BasisF<T> &b){return a.x <= b.x;}

template<class T> class BasisF{

public:
T x;
BasisF(const T &_x = T()): x(_x){}
BasisF(const BasisF &_b): x(_b.x){}
~BasisF(){}
BasisF& operator= (const T &_x){
x = _x;
return *this;
}
friend bool operator<=<>(const BasisF &a, const BasisF &b);
You don't need this friend declaration, 'x' is public.
};

#define min(a,b) ((a) <= (b) ? (a) : (b))
Ugh! If you are starting with templates, shouldn't you be getting rid of
all macros of that sort?

int main(){
BasisF<double> t(1);
if (min(t,2.0)<=0) return 1;
return 0;
}


The compiler can't figure out what 'T' should be for the ::operator<=
template (from the macro expansion) because one is 'BasesF<double>' and
the other is 'double'. It will not look for a conversion from those
types to some kind of common type and then use it as 'T'.

To solve it you need to add two more operators,

template<class T> bool operator<=(const BasisF<T>& a, const T& b)
{
return a.x <= b;
}

and

template<class T> bool operator<=(const T& a, const BasisF<T>& b)
{
return a <= b.x;
}

and then use literals of type 'double' to make your compiler resolve
the operators correctly. Otherwise, you could do

template<class T, class U>
bool operator<=(const T& a, const U& b)
{
return BasisF<T>(a).x <= BasisF<U>(b).x;
}

Victor
Jul 22 '05 #3

P: n/a
Boris wrote:
BasisF(const T &_x = T()): x(_x){}
The automatic transformation of a double or an int into a BasisF does
not work as you think it does.
friend bool operator<=<>(const BasisF &a, const BasisF &b);
Do you have a particular reason to want this operator as a friend
fonction rather than a member function?
if (min(t,2.0)<=0) return 1;


You could explicit BasisF<double>(0) instead of 0 and the same for 2.0,
if you do not want to make <= a member function or explicitly overload
<= for BasisF<double> and double.
Jul 22 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.