使用成员函数在 class 模板的实例之间进行转换

Converting between instances of a class template using a member function

我有几个强类型,它们只是包含有用共享代码的 class 模板的别名。

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>;

我想编写一个构造函数或辅助函数来帮助我将其中一种类型转换为另一种类型。

TilePosition tilePosition{1, 1};

ChunkPosition chunkPosition{tilePosition};
// or
ChunkPosition chunkPosition{tilePosition.asChunkPosition()};

此构造函数仅采用基础 xy 并使用常量缩放它们以匹配其他类型。

有没有办法做到这一点,或者我需要使用免费功能吗?

这是一种可能的通用解决方案,它允许您针对要允许的转换专门化一个 get_scaling_factor 函数:

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

}

接受的答案工作正常,但我最终做了一些不同的事情作为更通用的解决方案。

对于每一个我想添加功能的强类型,我都把它变成了一个完全派生的 class:

class ChunkPosition : public DiscretePosition<DiscreteImpl::ChunkTag>
{
public:
    ChunkPosition();

    ChunkPosition(int inX, int inY);

    explicit ChunkPosition(const TilePosition& tilePosition);
};

class TilePosition : public DiscretePosition<DiscreteImpl::TileTag>
{
public:
    TilePosition();

    TilePosition(int inX, int inY);

    explicit TilePosition(const ChunkPosition& chunkPosition);
};