I have a couple of strong types that are just aliases of a class template that contains useful shared code.
template <typename T>
struct DiscretePosition {
public:
int x{0};
int y{0};
// ... useful generic functions
};
struct ChunkTag{};
struct TileTag{};
using ChunkPosition = DiscretePosition<ChunkTag>;
using TilePosition = DiscretePosition<TileTag>;
I would like to write a constructor or helper function to help me convert one of these types to the other.
TilePosition tilePosition{1, 1};
ChunkPosition chunkPosition{tilePosition};
// or
ChunkPosition chunkPosition{tilePosition.asChunkPosition()};
This constructor would just take the underlying x, y and scale them to match the other type using a constant.
Is there a way to do this, or would I need to use a free function?
CodePudding user response:
Here is one possible generic solution that allows you to specialize a get_scaling_factor function for conversions you want to allow:
#include <iostream>
struct ChunkTag{};
struct TileTag{};
template<typename T, typename U>
consteval double get_scaling_factor();
template<>
consteval double get_scaling_factor<ChunkTag, TileTag>() {
return 2;
}
template <typename T>
struct DiscretePosition {
public:
int x{0};
int y{0};
// ... useful generic functions
DiscretePosition(int x, int y) : x(x), y(y) {}
template<typename U>
explicit DiscretePosition(const DiscretePosition<U>& other)
: x(other.x * get_scaling_factor<T, U>())
, y(other.y * get_scaling_factor<T, U>())
{}
};
using ChunkPosition = DiscretePosition<ChunkTag>;
using TilePosition = DiscretePosition<TileTag>;
int main() {
TilePosition tilePosition{1, 1};
ChunkPosition chunkPosition{tilePosition};
std::cout << chunkPosition.x << ", " << chunkPosition.y << std::endl;
// or
// ChunkPosition chunkPosition{tilePosition.asChunkPosition()};
}
