Reputation: 8126
Well, the correct title of this question should be "Circular dependency with classes which instances can be initialized one from another".
I have two classes (Index3i with integer data fields and Index3f with float data fields) that meant to be "convertible" one to another and vice versa:
File "Index3i.h":
// #include "Index3f.h"
class Index3i {
public:
Index3i()
: r(0), g(0), b(0) { }
Index3i(const Index3i& copy)
: r(copy.r), g(copy.g), b(copy.b) { }
// Index3i(const Index3f& copy)
// : r((int)copy.r), g((int)copy.g), b((int)copy.b) { }
// Index3f toIndex3f() { ... }
...
};
File "Index3f.h":
// #include "Index3i.h"
class Index3f {
public:
Index3f()
: r(0.0f), g(0.0f), b(0.0f) { }
Index3f(const Index3f& copy)
: r(copy.r), g(copy.g), b(copy.b) { }
// Index3f(const Index3i& copy)
// : r((float)copy.r), g((float)copy.g), b((float)copy.b) { }
// Index3i toIndex3i() { ... }
...
};
I need objects of Index3i
class to be able to initialize from and convert to objects of Index3f
class and the other way around. Also, I'd like to keep these classes header only.
Well, if I try to uncomment the commented constructors, methods and includes this creates a circular dependency problem. Another possible solution is to implement some conversion functions and put these in the third include file like "IndexConvert.h" or so.
But maybe there are other ways? Could you please suggest me an appropriate solution for the case?
Upvotes: 0
Views: 69
Reputation: 303147
Make them both a single class template - sounds like you don't actually need to have two different classes to begin with. That way, you can just write a converting constructor template:
template <class T>
class Index3 {
T r, g, b;
public:
Index3() : r(0), g(0), b(0) { }
Index3(const Index3&) = default;
template <class U, class = std::enable_if_t<std::is_convertible<U, T>::value>>
Index3(const Index3<U>& rhs)
: r(rhs.r), g(rhs.g), b(rhs.b)
{ }
/* rest */
};
Upvotes: 2