problem with simulating typedef templates

J

jimmy

I am trying to simulate typedef template similar to the suggestion of
Herb Sutter in the following article: http://www.gotw.ca/gotw/079.htm

However when implementing typedef templates according to his
suggestion, I run into type inference problems when passing typedef
templates as arguments to template functions. It seems the compiler
(gcc 4.0) cannot resolve the typedef template with an instantiation of
that typedef template. Below is an example to illustrate the exact
problem, along with the corresponding compiler error message. I would
like to the compiler to pattern match LinAlTraits<double>::Vector2 in
the function testThis, but instead it is trying to use the underlying
type boost::numeric::ublas::c_vector<double,2>. Any suggestions on a
workaround or idiom that would allow the syntactic nicety shown below
would be greatly appreciated.

#include <boost/numeric/ublas/vector.hpp>

template <typename Real>
struct LinAlTraits
{
typedef boost::numeric::ublas::c_vector<Real,2> Vector2;
};

template<typename T>
void
testThis(const typename LinAlTraits<T>::Vector2& v2)
{

}

int
main()
{
LinAlTraits<double>::Vector2 v2;
testThis(v2);
}

Here is the error message returned by gcc...

main.cc: In function 'int main()':
main.cc:20: error: no matching function for call to
'testThis(boost::numeric::ublas::c_vector<double, 2u>&)'

"g++" -Wall -ftemplate-depth-100 -O0 -fno-inline -g -c -o
"bin/gcc/debug/main.o" "main.cc"


Thanks,
Jimmy.
 
J

John Harrison

jimmy said:
I am trying to simulate typedef template similar to the suggestion of
Herb Sutter in the following article: http://www.gotw.ca/gotw/079.htm

However when implementing typedef templates according to his
suggestion, I run into type inference problems when passing typedef
templates as arguments to template functions. It seems the compiler
(gcc 4.0) cannot resolve the typedef template with an instantiation of
that typedef template. Below is an example to illustrate the exact
problem, along with the corresponding compiler error message. I would
like to the compiler to pattern match LinAlTraits<double>::Vector2 in
the function testThis, but instead it is trying to use the underlying
type boost::numeric::ublas::c_vector<double,2>. Any suggestions on a
workaround or idiom that would allow the syntactic nicety shown below
would be greatly appreciated.

#include <boost/numeric/ublas/vector.hpp>

template <typename Real>
struct LinAlTraits
{
typedef boost::numeric::ublas::c_vector<Real,2> Vector2;
};

template<typename T>
void
testThis(const typename LinAlTraits<T>::Vector2& v2)
{

}

int
main()
{
LinAlTraits<double>::Vector2 v2;
testThis(v2);
}

Here is the error message returned by gcc...

main.cc: In function 'int main()':
main.cc:20: error: no matching function for call to
'testThis(boost::numeric::ublas::c_vector<double, 2u>&)'

"g++" -Wall -ftemplate-depth-100 -O0 -fno-inline -g -c -o
"bin/gcc/debug/main.o" "main.cc"


Thanks,
Jimmy.

Right, C++ is limiteed in the parameter forms that can be deduced in a
template function. In particular if you write

template <T>
void func(typename A<T>::B p, ...

then the parameter p wil not take place in template argument deduction.

Usual workaround is to use iterators, in your case you could drop the
template typedef for testThis.

john
 
G

Gianni Mariani

jimmy said:
I am trying to simulate typedef template similar to the suggestion of
Herb Sutter in the following article: http://www.gotw.ca/gotw/079.htm

However when implementing typedef templates according to his
suggestion, I run into type inference problems when passing typedef
templates as arguments to template functions. It seems the compiler
(gcc 4.0) cannot resolve the typedef template with an instantiation of
that typedef template. Below is an example to illustrate the exact
problem, along with the corresponding compiler error message. I would
like to the compiler to pattern match LinAlTraits<double>::Vector2 in
the function testThis, but instead it is trying to use the underlying
type boost::numeric::ublas::c_vector<double,2>. Any suggestions on a
workaround or idiom that would allow the syntactic nicety shown below
would be greatly appreciated.

#include <boost/numeric/ublas/vector.hpp>

template <typename Real>
struct LinAlTraits
{
typedef boost::numeric::ublas::c_vector<Real,2> Vector2;
};

template<typename T>
void
testThis(const typename LinAlTraits<T>::Vector2& v2)
{

}

int
main()
{
LinAlTraits<double>::Vector2 v2;
testThis(v2);
}

The compiler can't automatically deduce that template's paramter. This
is the standard.

What's wrong with:

template<typename T>
void
testThis(const T& v2)
{
typedef typename T::value_type TReal;
//I'm not sure that boost/numeric/ublas/vector.hpp
//has a "value_type" but I suspect that it would.
}

Ok, so you want overloads as well.

This technique below is sometimes useful. When matching for template
functions, if there is an error when evaluating one of the template
function paramter types, that function is excluded from the search. Not
all compilers know how to do this properly yet. gcc 4 does, msvc7.1
ICE's sometimes.

#include <vector>

template <typename Real>
struct LinAlTraits
{
typedef std::vector<Real> Vector2;
};

template <typename T1, typename T2>
struct IsSame
{
};

template <typename T>
struct IsSame<T,T>
{
typedef int type;
};


template<typename T>
void
testThis(
const T & v2,
typename IsSame<T,typename LinAlTraits<typename
T::value_type>::Vector2>::type dummy = 0
)
{

}

int
main()
{
LinAlTraits<double>::Vector2 v2;

testThis(v2);

int vx;

testThis(vx);
}
 
J

jimmy

Thanks you for the responses. This inability to do this type of lookup
seems peculiar. If you are going to use the metafunction IsSame to
test if two types are the same, why can't the compiler do this
automatically? Can you point me to the standard, or maybe an
explanation of why this cannot be done. I could say this and this
would work...

boost::numeric::ublas::c_vector<Real,2> v1;
LinAlTraits<double>::Vector2 v2;
v2 = v1;

Also what about return types? Could I do something like this... I
think so.

template<typename Real>
typename LinAlTraits<Real>::Vector2
anotherTest(const boost::numeric::ublas::c_vector<Real,2>& v3)
{
return v3;
}

....

int main()
{
LinAlTraits<double>::Vector2 v3;
boost::numeric::ublas::c_vector<double,2> v4 = anotherTest(v3);
return 0;
}

I'm confused as to what type inferences the compiler can and cannot
make.

Thanks,
Jimmy.
 
J

jimmy

This should read...

boost::numeric::ublas::c_vector<doublel,2> v1;
LinAlTraits<double>::Vector2 v2;
v2 = v1;
 
G

Gianni Mariani

jimmy said:
Thanks you for the responses. This inability to do this type of lookup
seems peculiar. If you are going to use the metafunction IsSame to
test if two types are the same, why can't the compiler do this
automatically? Can you point me to the standard, or maybe an
explanation of why this cannot be done. I could say this and this
would work...

I don't have a reference to the standard handy, I do remember asking the
same question a few years ago (possibly on c.l.c++ so you'll kikely find
it in the google archives.) and I do believe there was a reference to
the standard made at the time. It's got somthing to do about looking
into a class, since classes can be (partially) specialized, it's very
hard to know which class your're talking about, i.e. there may be
multiple template parameters that yield the same type, hence the lookup
search would need to be exhaustive which is prohibitive.
boost::numeric::ublas::c_vector<Real,2> v1;
LinAlTraits<double>::Vector2 v2;
v2 = v1;

Also what about return types? Could I do something like this... I
think so.

template<typename Real>
typename LinAlTraits<Real>::Vector2
anotherTest(const boost::numeric::ublas::c_vector<Real,2>& v3)
{
return v3;
}

Yes. Template parameters are not deduced by return type except for the
conversion operator.
...

int main()
{
LinAlTraits<double>::Vector2 v3;
boost::numeric::ublas::c_vector<double,2> v4 = anotherTest(v3);
return 0;
}

I'm confused as to what type inferences the compiler can and cannot
make.

It can't look inside a class. The example I gave you earlier, can be
spoofed by a judicious specialization, which may be bad or good
depending on what you're trying to do.
 

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

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top