根据满足哪个概念决定实例化哪个模板
Decide which template to instantiate based on which concept is satisfied
假设我有两个概念:
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>;
};
然后我创建了一个模板化的 class,它受以下任一约束:
template<typename MeshType>
requires(ImplementsMeshGetters<MeshType> || ImplementsMeshGetters<MeshType>)
class Mesh
{
Vector3 GetPosition(uint i);
};
我想要 3 个版本的函数 GetPosition
专门化,一个用于第一个概念,一个用于第二个概念,还有一个以防万一编译器不知何故混淆,抛出一个错误来提醒用户class 没有正确编译。
我试过这个:
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++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;
};
只要没有重叠(比如当某些 MeshType
满足两个约束时),这就会起作用。因此 if constexpr
解决方案可能更稳健,因为它明确定义了重叠情况下的优先级。
注意:您的尝试看起来像是显式成员特化,它不会起作用,因为要特化一个成员函数,所有封闭模板也必须完全特化。
假设我有两个概念:
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>;
};
然后我创建了一个模板化的 class,它受以下任一约束:
template<typename MeshType>
requires(ImplementsMeshGetters<MeshType> || ImplementsMeshGetters<MeshType>)
class Mesh
{
Vector3 GetPosition(uint i);
};
我想要 3 个版本的函数 GetPosition
专门化,一个用于第一个概念,一个用于第二个概念,还有一个以防万一编译器不知何故混淆,抛出一个错误来提醒用户class 没有正确编译。
我试过这个:
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++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;
};
只要没有重叠(比如当某些 MeshType
满足两个约束时),这就会起作用。因此 if constexpr
解决方案可能更稳健,因为它明确定义了重叠情况下的优先级。
注意:您的尝试看起来像是显式成员特化,它不会起作用,因为要特化一个成员函数,所有封闭模板也必须完全特化。