Home > OS >  Converting between instances of a class template using a member function
Converting between instances of a class template using a member function

Time:01-05

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:

godbolt link

#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()};

}
  •  Tags:  
  • Related