How do I prevent a function template take precedence over inheritance?

D

DeMarcus

Hi,

I have a function template structure like this.

struct A
{
};

struct B : A
{
}

class SomeClass
{
public:

template<typename T>
void fnc( const T& t )
{
std::cout << "Template" << std::endl;
}

void fnc( const A& a )
{
std::cout << "Non-template" << std::endl;
}
};

int main()
{
SomeClass sc;
sc.fnc( A() ); // This gives me "Non-template".
sc.fnc( B() ); // Error! This gives me "Template"
// even though B inherits from A.
}

What's the proper way making instances of B access the non-templated
function?

Thanks,
Daniel
 
P

pfultz2

Hi,

I have a function template structure like this.

struct A
{

};

struct B : A
{

}

class SomeClass
{
public:

    template<typename T>
    void fnc( const T& t )
    {
       std::cout << "Template" << std::endl;
    }

    void fnc( const A& a )
    {
       std::cout << "Non-template" << std::endl;
    }

};

int main()
{
    SomeClass sc;
    sc.fnc( A() );  // This gives me "Non-template".
    sc.fnc( B() );  // Error! This gives me "Template"
                    // even though B inherits from A.

}

What's the proper way making instances of B access the non-templated
function?

Thanks,
Daniel

Use enable_if and make them both templates:
class SomeClass
{
public:

template<typename T>
void fnc( const T& t, typename enable_if<inherits<T, A> >::type *
dummy = 0 )
{
std::cout << "Inherits A" << std::endl;
}

template<typename T>
void fnc( const T& t )
{
std::cout << "Doesnt inherit A" << std::endl;
}

};

You can read about enable_if here: http://www.boost.org/doc/libs/1_42_0/libs/utility/enable_if.html
 
D

DeMarcus

Victor said:
It's not an error. The template, since it's allowed to be instantiated,
participates in the overload resolution. And because the compiler is
able to deduce 'T' as 'B' (most likely), its argument conversion
(reference binding, which is like the "identity") has a higher rank than
the non-template's "derived-to-base" conversion. That's why the
compiler picks the template.


Not "even though" but "because".


Use SFINAE, make your template function non-instantiatable for any class
that is derived from A. Utilize the 'enable_if' without making both
functions templates. Or invent your own way. For example, use the fact
that any class that derives from A has a member named 'A', with the same
level of access as the base class (public if derived publicly, etc.)


Ok, thanks!

Before I saw your post I did a solution like this.

class SomeClass
{
public:

template<typename T>
void fnc( const T& t )
{
std::cout << "Template" << std::endl;
}

void fnc( const A& a )
{
std::cout << "Non-template" << std::endl;
}

void fnc( const B& b )
{
fnc( static_cast<const A&>( b ) );
}

};

Is it bad practice to use static_cast?
 
M

Michael Doubez

Hi,

I have a function template structure like this.

struct A
{

};

struct B : A
{

}

class SomeClass
{
public:

    template<typename T>
    void fnc( const T& t )
    {
       std::cout << "Template" << std::endl;
    }

    void fnc( const A& a )
    {
       std::cout << "Non-template" << std::endl;
    }

};

int main()
{
    SomeClass sc;
    sc.fnc( A() );  // This gives me "Non-template".
    sc.fnc( B() );  // Error! This gives me "Template"
                    // even though B inherits from A.

}

What's the proper way making instances of B access the non-templated
function?

Another solution (apart from SFINAE) is to use a proxy class:

class SomeClass
{
public:

struct Generic
{
template<typename T>
Generic( const T& t )
{
std::cout << "Template" << std::endl;
}
};

void fnc( const Generic& g)
{
// possibly g.do_fnc(this);
}

void fnc( const A& a )
{
std::cout << "Non-template" << std::endl;
}
};

But it is not always practical.
 

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,813
Messages
2,569,696
Members
45,480
Latest member
CrazyMember

Latest Threads

Top