How to deal with template references?

G

gustavo.scotti

Hi.

What happens if a given template typename T is int& and you need to
reference an int pointer, or even an int?

e.g:

template <typename T>
void do_something( void *ptr, void(*funct)(T arg1)) {
funct( *(T *)ptr);
}

it's ok if you call it

void int_ok( int a);
int global = 123;
do_something( &global, int_ok);

but not ok if you call

void int_not_ok( int& a);
do_something( &global, int_not_ok);



if you don't use the templates, the logic is all ok, because a content
of a pointer can be referenced to a calling function.

by the way, the error caught is that you cannot reference a pointer to
a reference, like *(int& *). To my common sense, this is just like
*(int *).

Is there any obscure method to remove a reference from a template? :)
 
O

ondra.holub

1. I do not understand, why are you using void* instead of

template <typename T>
void do_something( T* ptr, void(*funct)(T arg1)) {
funct( *ptr);
}

2. If you are writing template parametrized with type T and you want to
have type U which is defined as
(a) if T is reference to X, U is X
(b) in any other case U is T
You can write it this way:

// Reference removal code
template<typename T>
struct RemoveRef
{
typedef T Type;
};

template<typename T>
struct RemoveRef<T&>
{
typedef T Type;
};

// Now you can use it
template<typename T>
struct HereINeedParameterWithoutReference
{
typedef
typename RemoveRef<T>::Type TWithoutReference;
};

3. An now forget previous rows. You need to change the template this
way and you have all you need:
template <typename T, typename F>
void do_something(T* ptr, F& funct)
{
funct(*ptr);
}
 
V

Victor Bazarov

Hi.

What happens if a given template typename T is int& and you need to
reference an int pointer, or even an int?

e.g:

template <typename T>
void do_something( void *ptr, void(*funct)(T arg1)) {
funct( *(T *)ptr);
}

it's ok if you call it

void int_ok( int a);
int global = 123;
do_something( &global, int_ok);

but not ok if you call

void int_not_ok( int& a);
do_something( &global, int_not_ok);



if you don't use the templates, the logic is all ok, because a content
of a pointer can be referenced to a calling function.

by the way, the error caught is that you cannot reference a pointer to
a reference, like *(int& *). To my common sense, this is just like
*(int *).

Is there any obscure method to remove a reference from a template? :)

It's not so obscure if you think about it. I think this should work:

template<class T> struct deReference {
typedef T type;
}
template<class T> struct deReference<T&> {
typedef typename deReference<T>::type type;
// and since there are no references to references, you might even do
// typedef T type;
// here, I guess
}

template <typename T>
void do_something( void *ptr, void(*funct)(T arg1)) {
funct( *(typename deReference<T>::type *)ptr);
}

V
 
V

Victor Bazarov

ondra.holub said:
[..forgotten..]
3. An now forget previous rows. You need to change the template this
way and you have all you need:
template <typename T, typename F>
void do_something(T* ptr, F& funct)
{
funct(*ptr);
}

Why 'F&'? Shouldn't it be just 'F funct'?

V
 
O

ondra.holub

Why 'F&'? Shouldn't it be just 'F funct'?

Well, it should be 'const F&'. For ordinary function it may be F only,
but const F& allows passing simple functor:

template <typename T, typename F>
void do_something(T* ptr, const F& funct)
{
funct(*ptr);
}

class Fn
{
public:
Fn() { }

void operator()(double prm) const
{
std::cout << "Fn::eek:perator()(" << prm << ")\n";
}
};

int main()
{
int global = 123;
do_something( &global, Fn());
}
 
V

Victor Bazarov

ondra.holub said:
Why 'F&'? Shouldn't it be just 'F funct'?

Well, it should be 'const F&'. For ordinary function it may be F only,
but const F& allows passing simple functor:
[..classical example redacted..]

Are you saying that having 'F funct' instead of 'F const& funct' does
not allow passing "simple functor"?

V
 
O

ondra.holub

No. Of course it allows (at least in case that copying is allowed). I
only wanted to pass instance of class (functor) in better way.

I think that the example would need to use better mechanism to select
best way to pass parameter (class instance with reference, basic types
with value), but such code would hide the answer to first question.
 
G

gustavo.scotti

Ondra,

Your RemoveRef typedef solved the problem. Congratulations! :)

1. I need to deference because I have the following code:


class BaseType {
protected:
const char *mName;
public:
BaseType() : mName(NULL) {}
BaseType( const BaseType& vrBaseType) : mName( NULL) {}

virtual void * GetAddress() const = 0;
virtual size_t GetSize() const = 0;
const char *GetName() const { return mName; }
};

template <typename T>
class VariantType : BaseType {
private:
const T& mItem;
public:
VariantType( const T& vItem) : mItem(vItem), BaseType() { mName =
typeid(vItem).name(); }
void* GetAddress() const { return (void *)&mItem; }
size_t GetSize() const { return sizeof(mItem); }
};


All I have access is BaseType, and it's type (because of template
completion).

template <class T_INSTANCE, typename T_FUNCTION >
class EventHandler : public IEventHandler {
protected:
T_INSTANCE* mpInstance;
T_FUNCTION mpFunction;
public:
EventHandler( T_INSTANCE* vpInstance, T_FUNCTION vpFunction):
mpInstance( vpInstance), mpFunction( vpFunction) {
}
void Execute( ParamHelper& vrHelper) {
vrHelper.Call( mpInstance, mpFunction);
}
};

the PAramHelper Call:

template <class T_INSTANCE, class A1>
void Call( T_INSTANCE* vpInstance,
void (T_INSTANCE::*vpFunction)(A1)) {
AssertType<A1>( 0);
(vpInstance->*vpFunction)(*(RemoveRef<A1>::Type
*)mArguments[0]->GetAddress()); }


And ParamHelper was previously parsed:

template<class A1>
void Parse( A1& arg1) {
Reset();
mArguments.Append() = (BaseType *) new VariantType<A1>( arg1);
}


Thank you all!
 

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
473,769
Messages
2,569,582
Members
45,060
Latest member
BuyKetozenseACV

Latest Threads

Top