Problem with function lookup and inheritance

S

StephQ

I need to know if it is possible to solve the following problem (I am
really stuck at it).

Consider the CRTP pattern:

struct Derived
{
....// May contain void operate( double x ) , may not.
};

template<class D>
struct Base : D
{
....// May contain void operate( double x ) , may not.
void set( double x )
{
static_cast<D*>( this )->operate( x );
}

};

D derived;
derived.set( 1.0 );

What I would like to accomplish, is to have derived.set( 1.0 ) behave
EXACTLY as if the set function were defined inside of Derived.

More precisely, I would like to obtain the same "function lookup"
behaviour for "operate" that I would obtain if set were defined inside
Derived, that is: search for operate inside of Derived, and if not
present search for it inside Base, and if not present gives compile
error.

I know I can search for the existence of "operate" in Derived using
SFINAE to decide if I should do the cast or not.
However, this does not solve my problem because what happens in
reality is that "operate" can be defined in another class from which
Derived inherits.

Basically, I need "something like" static_cast that also searches in
the bases of the converted class, and not only in the particular
converted class. Something like *moving the lookup starting point".

This is the key problem that I need to solve to finish a component of
my library.
Thank you very much in advance for any help.

Best Regards
StephQ
 
A

Alf P. Steinbach

* StephQ:
More precisely, I would like to obtain the same "function lookup"
behaviour for "operate" that I would obtain if set were defined inside
Derived, that is: search for operate inside of Derived, and if not
present search for it inside Base, and if not present gives compile
error.

What's wrong with simply calling the function, then?

Cheers, & hth.,

- Alf
 
A

Alf P. Steinbach

* StephQ:
I need to know if it is possible to solve the following problem (I am
really stuck at it).

Consider the CRTP pattern:

struct Derived
{
...// May contain void operate( double x ) , may not.
};

template<class D>
struct Base : D
{
...// May contain void operate( double x ) , may not.
void set( double x )
{
static_cast<D*>( this )->operate( x );
}

};

Sorry, I didn't see this at first reply, but hey, you're naming a base
class "Derived" and a derived class "Base".

That confusion may be part of your problem.

Or not. :)


Cheers, & hath.,

- Alf
 
V

Victor Bazarov

Alf said:
* StephQ:

What's wrong with simply calling the function, then?

StephQ doesn't seem to want to call the function if it's defined in
one of the base classes of the 'D' type (inside the 'Base' template).

Of course I may have misunderstood.

V
 
S

StephQ

I just discovered (I made a slight error in my code example) that the
previous example works fine if "operate" is in Derived or in another
class (not Base) from which Derived inherits.
So it seems that static_cast is actually doing what I am demanding and
the lookup searches for operate in the base classes.

However I still have TWO problem with my example. Consider the
following code:

// mu and sigma are just empty struct in namespace tag for tagging
purpouses.

template<class D>
struct par
{
template<class A1>
void set( const A1& a1 )
{
typedef typename A1::key_type tag1;
static_cast<D*>( this )->set_obj( a1, tag1() );
}

template<class A>
void set_obj( const A& a, tag::mu )
{
}

template<class A>
void set_obj( const A& a, tag::sigma )
{
}
};

struct muvar
{
typedef tag::mu key_type;
};

struct sigmavar
{
typedef tag::sigma key_type;
};

class Base : public par<Base>
{
public:

using par<Base>::set;
};

class Derived : public par<Derived>, public Base
{
public:

//template<class A>
//void set_obj( const A& a, tag::mu )
//{
//}
//template<class A>
//void set_obj( const A& a, tag::sigma )
//{
//}

using par<Derived>::set;
};

int main()
{
Derived derived;

derived.set( muvar() );
}

Basically I am using tags to select the implementation. The
implementation inside par is the default one.
However this code does not work in the following situations:

1) set_obj is only in par (as in the code here) => I get ambiguous
error
2) set_obj( const A& a, tag::sigma ) is uncommented in Derived => I
get no overload found error

How can I solve these problems?

Thank you.

StephQ
 
S

StephQ

StephQ doesn't seem to want to call the function if it's defined in
one of the base classes of the 'D' type (inside the 'Base' template).

Of course I may have misunderstood.

V

See my last reply. Basically for a given tag (say tag::mu) I want to
select set_obj( .., tag::mu) searching first in Derived, and then if
not present in all the bases of Derived. Obviously I am perfectly fine
with getting an error if two ore more candidates are present.
But I can not get this working with this implementation.

Thank you for your replies.

Best Regards
StephQ
 
X

xtrigger303

See my last reply. Basically for a given tag (say tag::mu) I want to
select set_obj( .., tag::mu) searching first in Derived, and then if
not present in all the bases of Derived. Obviously I am perfectly fine
with getting an error if two ore more candidates are present.
But I can not get this working with this implementation.

Thank you for your replies.

Best Regards
StephQ

Hi,
IMHO, try avoiding MI. Check the following.
Regards,
Francesco

namespace tag
{
struct mu {};
struct sigma {};
}

template< typename TBridge >
struct CBridger : TBridge {};

template< >
struct CBridger< void > {};


//template<class D>
template<class D, typename TBridge = void >
//struct par
struct par : CBridger< TBridge >
{
template<class A1>
void set( const A1& a1 )
{
typedef typename A1::key_type tag1;
static_cast<D*>( this )->set_obj( a1, tag1() );
}

template<class A>
void set_obj( const A& a, tag::mu )
{
}

template<class A>
void set_obj( const A& a, tag::sigma )
{
}

};

struct muvar
{
typedef tag::mu key_type;
};

struct sigmavar
{
typedef tag::sigma key_type;
};

class Base : public par<Base>
{
public:
using par<Base>::set;

};

//class Derived : public par<Derived>, public Base
class Derived : public par<Derived, Base >
{
public:
//template<class A>
//void set_obj( const A& a, tag::mu )
//{
//}
template<class A>
void set_obj( const A& a, tag::sigma )
{
}

using par<Derived, Base>::set;
using par<Derived, Base >::set_obj;

};

int main()
{
Derived derived;
derived.set( muvar() );

}
 

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,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top