Is it possible to avoid defining the same functions for structs A, B below twice? Their members are named exactly the same, but the v0, v1 ... vN members are of different type between the two structs A and B. If it helps the members v* are all derived from the same struct V.
Non-trivial functions (i.e. assignment =) can reuse a templated copy function outside the structs, like below, but it'd be preferred/cleaner if this was defined once and within the struct.
Is there a clean way to templatize A and B definition into a single one?
template <class T1, class T2>
void copy(T1& to, T2& from)
{
to.v0 = from.v0;
to.v1 = from.v1;
to.type = from.type;
}
enum class E { TYPE_0, TYPE_1 };
struct B;
struct A
{
C0<float> v0;
C1<int> v1;
E type;
A& operator = (const B& t)
{
copy(*this, t);
return *this;
}
string strType() { return string(type); }
};
struct B
{
D0<float> v0;
D1<int> v1;
E type;
B& operator = (const A& t)
{
copy(*this, t);
return *this;
}
string strType() { return string(type); }
}
You can keep a common
base template class for the common functionalities and inherit from it for class A
and B
.
However, the copy assignment operator is a special member function, which I do not think one could template for different types return in the base class. Therefore you need to provide for each class.
Meaning, you can do
enum class E { TYPE_0, TYPE_1 };
struct B;
template<typename ClassA, typename ClassB> struct Common
{
template<E type>
std::string strType() { return std::to_string(static_cast<int>(type)); }
// need to cast the type to int before you convert std::to_string
// other common-member-functions
};
struct A : public Common<A, B>
{
C0 v0;
C1 v1;
E type;
// ... A& operator = (const B& t)
// bring the common functionalities to A
using Common<A, B>::strType;
// ... other member-functions
};
struct B : public Common<B, A>
{
D0 v0;
D1 v1;
E type;
// ... B& operator = (const A& t)
// bring the common functionalities to A
using Common<B, A>::strType;
// ... other member-functions
};
However, both structs A
, B
, seems to only differ from the two members (i.e. C0
, C1
and D0
, D1
respectively), combining both classes to one by making a class-template, also an alternative:
Following is an example code:
#include <iostream>
#include <vector>
#include <string>
enum class E { TYPE_0, TYPE_1 };
template<typename T1, typename T2>
struct AandB
{
T1 v0;
T2 v1;
E type;
AandB() : type{ E::TYPE_0 } {}
AandB& operator= (const AandB& rhs) // one operator =
{
v0 = rhs.v0;
v1 = rhs.v1;
type = rhs.type;
return *this;
}
std::string strType() const { return std::to_string(static_cast<int>(type)); }
};
int main()
{
using C0 = std::vector<float>;
using C1 = std::vector<int>;
AandB<C0, C1> obj;
std::cout << obj.strType() ; // Prints: 0
}