【问题标题】:Decide which template to instantiate based on which concept is satisfied根据满足哪个概念来决定要实例化哪个模板
【发布时间】:2021-07-31 08:29:45
【问题描述】:

假设我有两个概念:

struct Vector3 {float x; float y; float z;};

template<typename T> concept ImplementsMeshGetters = requires(T a, uint index)
{
    { a.Position(index) }->std::convertible_to<Vector3>;
};

template<typename T> concept HasMeshMemberArrays = requires(T a, uint index)
{
    { a.positions[index] }->std::convertible_to<Vector3>;
};

我创建了一个模板类,它受任一者的约束:

template<typename MeshType>
requires(ImplementsMeshGetters<MeshType> || ImplementsMeshGetters<MeshType>)  
    class Mesh 
    {
           Vector3 GetPosition(uint i);
    };

我想要 3 个版本的函数 GetPosition 专门化,一个用于第一个概念,一个用于第二个概念,一个用于以防编译器不知何故混淆,这会引发错误以提醒用户该类不是' t 编译正确。

我试过了:


template<ImplementsMeshGetters MeshType>
Eigen::Vector3f AnimationMesh<MeshType>::GetPosition(uint i)
{
    return mesh.Position(i);
};

template<HasMeshMemberArrays MeshType>
Eigen::Vector3f AnimationMesh<MeshType>::GetPosition(uint i)
{
    return mesh.positions[i];
}

template<> Eigen::Vector3f AnimationMesh<typename T>::GetPosition(uint i)
{
    Assert(
        false,
        "Somehow the mesh doesn't obey either of it's constraints. Your compiler "
        "is likely broken.");
    return {0, 0, 0};
}

但它无法编译,因为我正在重新定义相同的符号。

我可以这样做:

template<typename MeshType> Vector3 AnimationMesh<MeshType>::GetPosition(uint i)
{
    if constexpr(ImplementsMeshGetters<MeshType>)
    {  //
        return mesh.Position(i);
    }
    else if constexpr(HasMeshMemberArrays<MeshType>)
    {
        return mesh.positions[i];
    }
    else
        constexpr
        {
            Assert(
                false,
                "Somehow the mesh doesn't obey either of it's constraints. Your compiler "
                "is likely broken.");
            return {0, 0, 0};
        }
};

但这比我可以实例化模板有点丑。

【问题讨论】:

  • 这与试图特化模板类的方法没有什么不同:你不能,你必须首先特化模板。通常的解决方案是让方法使用辅助类重新调用适当的方法,然后专门化辅助类。
  • 猜猜我将不得不采用第二种解决方案

标签: c++ templates template-meta-programming c++20 c++-concepts


【解决方案1】:

在 C++20 中,您可以定义受约束的成员函数:

template <typename MeshType>
class Mesh {
public:
  Vector3 GetPosition(uint i) requires ImplementsMeshGetters<MeshType> {
    return mesh.Position(i);
  }
  Vector3 GetPosition(uint i) requires HasMeshMemberArrays<MeshType> {
    return mesh.positions[i];
  }
private:
  MeshType mesh;
};

Live demo

只要没有重叠(例如某些MeshType 满足这两个约束),这将起作用。因此,if constexpr 解决方案可能更稳健,因为它清楚地定义了重叠情况下的优先级。

注意:您的尝试看起来像是显式成员特化,它不起作用,因为要特化成员函数,所有封闭模板也必须完全特化。

【讨论】:

    猜你喜欢
    • 2020-05-14
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多