Is it possible that some types of specialized class share one non-template member function definition of a declaration, some types of specialized class share another non-template member function definition with the same declaration in class as above, and the function definitions is in cpp not hpp?
for example: I have a template class A with non-template member function p
template <typename T>
class A {
void p() {
print("food.\n");
}
};
And I have 4 types: banana, apple, fish, steak to specialize the class A for usage in main.cpp: if A is specialized as A<banana>, A<apple>, p print "fruit", if A is specialized as A<fish>, A<steak>, p print "meat".
I would not write 2 times of version: print "fruit" 2 times of version: print "meat" 2 times. Meanwhile, since which type of specialized class print what text has been concrete, is it possible that the 2 versions of p definition could be write in cpp files to reduce cost of compilation?
CodePudding user response:
Maybe use if constexpr
to check types and print accordingly.
#include <iostream>
struct Fish {};
struct Steak {};
struct Banana {};
struct Apple {};
template <typename T>
class A {
public:
void p() {
if constexpr(std::is_same_v<T, Apple> || std::is_same_v<T, Banana>)
std::cout << "Fruit\n";
else if constexpr(std::is_same_v<T, Fish> || std::is_same_v<T, Steak>)
std::cout << "Meat\n";
}
};
int main()
{
A<Fish> fish;
A<Apple> apple;
fish.p();
apple.p();
}
CodePudding user response:
Inheritance might help you out in this case:
class Fruit
{
protected:
void p() { /* ... */ }
};
class Meat
{
protected:
void p() { /* ... */ }
};
// general case left unimplemented not to allow arbitrary instantiations
template <typename T>
class A;
// (alternatively you might provide a default implementation handling the unspecific case)
template <>
class A<Apple> : Fruit
{
public: using Fruit::p;
};
template <>
class A<Fish> : Meat
{
public: using Fruit::p;
};
If it is meaningful to provide a public type hierarchy is up to you to decide, you might then add a generic root class Food
with a pure virtual p
(then public, of course) while you'd let Fruit
and Meat
have override
ing p
. This would e.g. allow to add the different types of food to a container, but you need to use (smart?) pointers for to avoid object slicing.
Public inheritance with public p
in the base classes could be applied for convenience only, too, for not having to specify the using
clause – though convenience for the implementer of types usually leads to less clean code in the end...