Reputation: 258
#include <iostream>
using namespace std;
class c1 {
public:
void f1() { std::cout << "In f1\n"; }
};
class c2 {
public:
void f2() { std::cout << "In f2\n"; }
};
template<typename T>
class C: public c1, c2 {
public:
void f() {
};
};
int main() {
C<c2> c;
c.f();
return 0;
}
is there any way based on T
the function f
in C
can be mapped to function f1
in c1
and f2
in c2
? I am not clear how function f
that can be used as a wrapper around f1
and f2
when i am pointing to a specific class using T
Note: I cannot modify class c1
and c2
. its out of my scope.
Upvotes: 3
Views: 77
Reputation: 3873
You can specialise template:
#include <iostream>
using namespace std;
class c1{
public:
void f1(){std::cout<<"In f1\n";}
};
class c2{
public:
void f2(){std::cout<<"In f2\n";}
};
template <typename T>
class C:public c1, c2 {
public:
void f()
{
};
};
template<> class C<c1>:public c1, c2 {
public:
void f()
{
c1::f1();
};
};
template<> class C<c2>:public c1, c2 {
public:
void f()
{
c2::f2();
};
};
int main()
{
C<c2> c;
c.f();
return 0;
}
Upvotes: 0
Reputation: 170065
Yes, you can write a template like that. In several ways in fact. If you want to keep C
as it is, then it's a simple matter of adding a type trait which contains a pointer to a member function
template<typename> struct which_member;
template<> struct which_member<c1> {
static constexpr void (c1::* func)() = &c1::f1;
};
template<> struct which_member<c2> {
static constexpr void (c2::* func)() = &c2::f2;
};
void f() {
(static_cast<T*>(this)->*which_member<T>::func)();
}
The key is here (static_cast<T*>(this)->*which_member<T>::func)();
. We cast this
to the appropriate type pointer, then use the trait to retrieve the pointer to a member. And finally we use the access operator ->*
on these two operands to obtain a callable expression. Which we then call (the outer ()
).
The cast isn't strictly needed, but I think the error message is more descriptive of the problem if you pass something that isn't a base class of C
as the type parameter.
Upvotes: 2
Reputation: 172894
You can use constexpr if from C++17. e.g.
void f() {
if constexpr (std::is_same_v<T, c1>)
f1();
else
f2();
}
Note that constexpr if is evaluated at compile-time, as @skypjack commented, for this case, it's pretty fine to be evaluated at run-time too. So the following code works fine too:
void f() {
if (std::is_same_v<T, c1>)
f1();
else
f2();
}
Upvotes: 3