template question

V

Valeriu Catina

Hi,

given the next code:


#define ENUM_CAST(x) int(x)

template<class T,int N>
class Array
{
public:
enum { rank = N };

protected:

// members ...

template<bool>
struct Select{ };

public:

template<class T_expr>
Array& evaluate(T_expr expr, Select<true>& )
{
// ... code
return *this;
}

template<class T_expr>
Array& evaluate(T_expr expr, Select<false>& )
{
// ... code
return *this;
} template<class T_expr>
Array& evaluateExpr(T_expr expr)
{
return
evaluate(expr,Select<ENUM_CAST(rank)==ENUM_CAST(T_expr::rank)>());
}

public:
// ctors, dtor, function members ...
};

template<class T,int N>
class SomeExpr
{
public:
enum { rank = N };
};

void testFunc()
{
Array<double,2> A;
SomeExpr<double,2> x;
SomeExpr<double,1> y;

A.evaluateExpr(x);
A.evaluateExpr(y);

}

Intel c++ for linux and g++ 3.3.1 do not compile the code (the error
messages are below). In the meantime Intel c++ for Windows compiles it.
If I change the evaluate member functions like below

template<class T_expr>
Array& evaluate(T_expr expr, Select<true> )
{
// ... code
return *this;
}

template<class T_expr>
Array& evaluate(T_expr expr, Select<false> )
{
// ... code
return *this;
}
the compilation succedes.

Which compiler is right ?



Here is the output of the compiler (g++ 3.3.1):

stest.cpp: In member function `Array<T, N>& Array<T,
N>::evaluateExpr(T_expr) [with T_expr = SomeExpr<double, 2>, T = double,
int N = 2]':
stest.cpp:57: instantiated from here
stest.cpp:36: error: no matching function for call to `Array<double,
2>::evaluate(SomeExpr<double, 2>&, Array<double, 2>::Select<true>)'
stest.cpp:21: error: candidates are: Array<T, N>& Array<T,
N>::evaluate(T_expr, Array<T, N>::Select<true>&) [with T_expr =
SomeExpr<double, 2>, T = double, int N = 2]
stest.cpp:28: error: Array<T, N>& Array<T,
N>::evaluate(T_expr, Array<T, N>::Select<false>&) [with T_expr =
SomeExpr<double, 2>, T = double, int N = 2]
stest.cpp: In member function `Array<T, N>& Array<T,
N>::evaluateExpr(T_expr) [with T_expr = SomeExpr<double, 1>, T = double,
int N = 2]':
stest.cpp:58: instantiated from here
stest.cpp:36: error: no matching function for call to `Array<double,
2>::evaluate(SomeExpr<double, 1>&, Array<double, 2>::Select<false>)'
stest.cpp:21: error: candidates are: Array<T, N>& Array<T,
N>::evaluate(T_expr, Array<T, N>::Select<true>&) [with T_expr =
SomeExpr<double, 1>, T = double, int N = 2]
stest.cpp:28: error: Array<T, N>& Array<T,
N>::evaluate(T_expr, Array<T, N>::Select<false>&) [with T_expr =
SomeExpr<double, 1>, T = double, int N = 2]


and Intel (icc) 7.1 for linux:

stest.cpp(37): error: no instance of overloaded function "Array<T,
N>::evaluate [with T=double, N=2]" matches the argument list
argument types are: (SomeExpr<double, 2>, Array<double,
2>::Select<true>)
evaluate(expr,Select<ENUM_CAST(rank)==ENUM_CAST(T_expr::rank)>());
^
detected during instantiation of "Array<T, N> &Array<T,
N>::evaluateExpr(T_expr) [with T=double, N=2, T_expr=SomeExpr<double, 2>]"

stest.cpp(37): error: no instance of overloaded function "Array<T,
N>::evaluate [with T=double, N=2]" matches the argument list
argument types are: (SomeExpr<double, 1>, Array<double,
2>::Select<false>)
evaluate(expr,Select<ENUM_CAST(rank)==ENUM_CAST(T_expr::rank)>());
^
detected during instantiation of "Array<T, N> &Array<T,
N>::evaluateExpr(T_expr) [with T=double, N=2, T_expr=SomeExpr<double, 1>]"

compilation aborted for stest.cpp (code 2)
 
G

Gianni Mariani

Valeriu Catina wrote:
....
Array& evaluateExpr(T_expr expr)
{
return
evaluate(expr,Select<ENUM_CAST(rank)==ENUM_CAST(T_expr::rank)>());

try :

evaluate<T>(expr,Select<ENUM_CAST(rank)==ENUM_CAST(T_expr::rank)>());

The problem is obviously in overload resolution and the standard is very
wordy about how and how not to resolve. I have yet to grok all of that
but I think that since your implicitly doing a conversion (from Select<>
to a Select<>&), it is not able to find a corresponding template to
resolve for.
 
R

Rob Williscroft

Valeriu Catina wrote in
Hi,

given the next code:


#define ENUM_CAST(x) int(x)

template<class T,int N>
class Array
{
public:
enum { rank = N };

protected:

// members ...

template<bool>
struct Select{ };

public:

template<class T_expr>
Array& evaluate(T_expr expr, Select<true>& )

Make this:

Array& evaluate(T_expr expr, Select<true> const & )

or as you've found out yourself:

Array& evaluate(T_expr expr, Select<true> )

[snip]
Array& evaluateExpr(T_expr expr)
{
return

Here you try to "bind" a temporary ( the Select<...>() ) to a
non-const reference, this is illegal in Standard C++, the compiler
that excepts it is probably operating in a msvc v6.0 compatibility
mode.
Which compiler is right ?

The one('s) that gave you the error.

HTH

Rob.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,824
Members
47,370
Latest member
desertedtyro29

Latest Threads

Top