By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,496 Members | 1,266 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,496 IT Pros & Developers. It's quick & easy.

Problem with function lookup and inheritance

P: n/a
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
Dec 7 '07 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Alf P. Steinbach wrote:
* 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?
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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 7 '07 #2

P: n/a
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
Dec 7 '07 #3

P: n/a
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
Dec 7 '07 #4

P: n/a
On Dec 7, 7:54 pm, StephQ <askmeo...@mailinator.comwrote:
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
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() );

}
Dec 9 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.