How to convert (type *) to (type) inside a template?

M

Marcin Kalicinski

Hi,

How to convert a type inside a template from pointer to type to type itself?

struct S { };

template<class It> void f(It begin, It end)
{
// When called from g(), It::value_type is a pointer to S, but
// I want to get S itself, for example to use it in an auto_ptr:
auto_ptr<It::*value_type> ap = **begin; // this will not work
}

void g()
{
std::vector<S *> v;
f(v.begin(), v.end());
}

There's a way to make pointer type from regular type (just by adding *), but
is there a way to do the reverse?

Best regards,
Marcin
 
J

John Harrison

Marcin Kalicinski said:
Hi,

How to convert a type inside a template from pointer to type to type itself?

struct S { };

template<class It> void f(It begin, It end)
{
// When called from g(), It::value_type is a pointer to S, but
// I want to get S itself, for example to use it in an auto_ptr:
auto_ptr<It::*value_type> ap = **begin; // this will not work
}

void g()
{
std::vector<S *> v;
f(v.begin(), v.end());
}

There's a way to make pointer type from regular type (just by adding *), but
is there a way to do the reverse?

Best regards,
Marcin

Partial template specialization will do the trick (but not all compilers
support it)

Untested code

template <class T>
struct UnPtr
{
};

template <class T>
struct UnPtr<T*>
{
typedef T type;
};

template<class It> void f(It begin, It end)
{
// When called from g(), It::value_type is a pointer to S, but
// I want to get S itself, for example to use it in an auto_ptr:
auto_ptr<UnPtr<It::value_type>::type > ap = **begin; // this will not
work
}

john
 
J

John Harrison

John Harrison said:
Partial template specialization will do the trick (but not all compilers
support it)

Untested code

template <class T>
struct UnPtr
{
};

template <class T>
struct UnPtr<T*>
{
typedef T type;
};

Actually I think that above is rubbish. Apologies, I'll go away and actually
test something.

john
 
A

Alf P. Steinbach

Actually I think that above is rubbish. Apologies, I'll go away and actually
test something.

Uh, why?

I had to look in Andrei's book, but he uses the same technique.

Here's my test code:


#include <memory> // std::auto_ptr
#include <iostream> // std::cout
#include <typeinfo>

template< typename P >
struct PointerTraits {};

template< typename ABaseType >
struct PointerTraits<ABaseType*>
{
typedef ABaseType BaseType;
};



template< typename Pointer >
void f( Pointer p )
{
typedef PointerTraits<Pointer>::BaseType BaseType;
std::cout << typeid( Pointer ).name() << std::endl;
std::cout << typeid( BaseType ).name() << std::endl;
}

int main(){ int x; f( &x ); }
 
G

Guillaume Brocker

Marcin said:
Hi,

How to convert a type inside a template from pointer to type to type itself?

struct S { };

template<class It> void f(It begin, It end)
{
// When called from g(), It::value_type is a pointer to S, but
// I want to get S itself, for example to use it in an auto_ptr:
auto_ptr<It::*value_type> ap = **begin; // this will not work
^
|
+-- You cannot place '*' here !
}

void g()
{
std::vector<S *> v;
f(v.begin(), v.end());
}

There's a way to make pointer type from regular type (just by adding *), but
is there a way to do the reverse?

Best regards,
Marcin

I think that you will need to pass one more template parameter to the
function f since there is currently no possible way to deduce the S type
from It::value_type.

Furthermore, you can't dereference a pointer type by placing a start
ahead (see your annotated code sample) like dereferencing a pointer
(that is an address to an object).

Example:

typedef int* A;
typedef *Ptr B; // Wrong
 
A

Alf P. Steinbach

* Guillaume Brocker said:
I think that you will need to pass one more template parameter to the
function f since there is currently no possible way to deduce the S type
from It::value_type.

That turns out not to be the case.

In fact S can easily be deduced from S*.

See the rest of the thread.
 
M

Marcin Kalicinski

Hi All,

Thanks for the partial template specialization solution. Unfortunately, I
use Visual C++ 7.0 (not 7.1), which does not support it. I could not even
test if it works :-(

Is there any technique that does not rely on partial template
specialization?

Kind regards,
Marcin


U¿ytkownik "Marcin Kalicinski" <[email protected]> napisa³ w wiadomoœci
Hi,

How to convert a type inside a template from pointer to type to type itself?

struct S { };

template<class It> void f(It begin, It end)
{
// When called from g(), It::value_type is a pointer to S, but
// I want to get S itself, for example to use it in an auto_ptr:
auto_ptr<It::*value_type> ap = **begin; // this will not work
}

void g()
{
std::vector<S *> v;
f(v.begin(), v.end());
}

There's a way to make pointer type from regular type (just by adding *), but
is there a way to do the reverse?

Best regards,
Marcin
 
A

Alf P. Steinbach

* "Marcin Kalicinski said:
Thanks for the partial template specialization solution. Unfortunately, I
use Visual C++ 7.0 (not 7.1), which does not support it. I could not even
test if it works :-(

Please do not top-post.

Regarding partial template specialization you can often simulate it by using
nested template classes or functions.

However, I suspect that's not possible in this case, mainly because the VC 7.0
port of Loki TypeTraits does not implement this functionality. If it were
possible I think it would be there. So, practical solution, more arguments.
 
J

John Harrison

Alf P. Steinbach said:
Uh, why?

I had to look in Andrei's book, but he uses the same technique.

I got worried because I hadn't tested the code. I convinced myself that the
T in 'typedef T type' was the pointer type not the type pointed to. Seems I
was wrong so I apologise for my apology!

john
 
J

Jeff Schwab

Alf said:
Uh, why?

I had to look in Andrei's book, but he uses the same technique.

Here's my test code:


#include <memory> // std::auto_ptr
#include <iostream> // std::cout
#include <typeinfo>

template< typename P >
struct PointerTraits {};

template< typename ABaseType >
struct PointerTraits<ABaseType*>
{
typedef ABaseType BaseType;
};



template< typename Pointer >
void f( Pointer p )
{
typedef
typename

PointerTraits<Pointer>::BaseType BaseType;
std::cout << typeid( Pointer ).name() << std::endl;
std::cout << typeid( BaseType ).name() << std::endl;
}

int main(){ int x; f( &x ); }


I'm still not clear on when "typename" is(not) needed, but GCC insists
on it in this case.
 
N

Niklas Borson

John Harrison said:
Marcin Kalicinski said:
Hi,

How to convert a type inside a template from pointer to type to type itself?
[snip]

Partial template specialization will do the trick (but not all compilers
support it)

Untested code

template <class T>
struct UnPtr
{
};

template <class T>
struct UnPtr<T*>
{
typedef T type;
};

template<class It> void f(It begin, It end)
{
// When called from g(), It::value_type is a pointer to S, but
// I want to get S itself, for example to use it in an auto_ptr:
auto_ptr<UnPtr<It::value_type>::type > ap = **begin; // this will not
work
}

What would UnPtr<int>::type give you then? Or UnPtr<int***>::type?
Perhaps the following slight modification would be more flexible...

template<class T>
struct UnPtr
{
typedef T type;
};

template<class T>
struct UnPtr<T*>
{
typedef typename UnPtr<T>::type type;
};

void f()
{
UnPtr<int>::type i = 1;
UnPtr<int****>::type j = 1;
}
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top