如何根据参数化类型的特定成员的类型对模板类函数进行不同的实现
How to have different implementation of a template class function based on the type of a specific member of the parameterized type
所以这是简化的问题,假设我们有两种类型
struct Shape2D
{
Vec2 Position;
};
struct Shape3D
{
Vec3 Position;
};
我想创建一个模板类测试
template<class T>
class Test
{
public:
int method1()
{
//return 1 if member T::Position is Vec2,
//return 2 if member T::Position is Vec3
}
}
以便以下代码有效
Test<A> ta;
Test<B> tb;
assert(ta.method1() == 1);
assert(tb.method1() == 2);
此问题的真实上下文是针对OpenGL引擎的。我希望能够对 2D 和 3D 顶点数据使用相同的序列化类,而无需编写 3D 和 2D 版本。
有几种方法可以解决这个问题。
最简单的方法是只使用正常的重载分辨率:
template<class T>
class Test
{
private:
T myT;
int internal(Vec2)
{
return 1;
}
int internal(Vec3)
{
return 2;
}
public:
Test() : myT{} {}
int method1()
{
return internal(myT.Position);
}
};
这要求您实际具有 T
的实例。 如果没有,则需要使用基于模板的方法。 这是一个相当深入的主题,但是在您的示例中可以执行您想要的一种方法是:
template <typename T>
int internal();
template <>
int internal<Vec2>()
{
return 1;
}
template <>
int internal<Vec3>()
{
return 2;
}
template<class T>
class Test
{
public:
int method1()
{
return internal<decltype(T::Position)>();
}
};
您可以使用几个函数声明(在这种情况下不需要定义(,std::declval
和std::integral_constant
在编译时解决它。
它遵循一个最小的工作示例:
#include<type_traits>
#include<utility>
struct Vec2 {};
struct Vec3{};
struct Shape2D { Vec2 Position; };
struct Shape3D { Vec3 Position; };
template<class T>
class Test {
static constexpr std::integral_constant<int, 1> method1(Vec2);
static constexpr std::integral_constant<int, 2> method1(Vec3);
public:
constexpr int method1() {
return decltype(method1(std::declval<T>().Position))::value;
}
};
int main() {
Test<Shape2D> ta;
Test<Shape3D> tb;
static_assert(ta.method1() == 1, "!");
static_assert(tb.method1() == 2, "!");
}
如果T
没有名为 Position
的数据成员,则上述解决方案无法编译,其类型为 Vec2
或 Vec3
。
另一种需要默认值的可能方法是:
constexpr int method1() {
return
(std::is_same<decltype(std::declval<T>().Position), Vec2>::value
? 1 : (std::is_same<decltype(std::declval<T>().Position), Vec3>::value
? 2 : 0));
}
那是与std::is_same
结合使用的三元运算符,仅此而已。
如果可以使用 C++17,则还可以将解决方案基于if/else constexpr
:
constexpr int method1() {
if constexpr(std::is_same_v<decltype(std::declval<T>().Position), Vec2>) {
return 1;
} else if constexpr(std::is_same_v<decltype(std::declval<T>().Position), Vec3>) {
return 2;
}
}
<</div>
div class="answers">你可以有一些oveload函数来运行不同的代码,比如你有int func (shape 2D x)
和int func (shape3D x)
,所以你只需调用func (T.position)
method1
,编译器就会帮助你解决调用。
相关文章:
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- C++ 在外部使用嵌套结构实现类函数
- 正确实现类函数数组
- 我能否通过将函数实现为类对象方法来避免使用互斥锁
- 关于C++从派生类调用在基类中实现的虚拟函数的问题
- 使用初始值设定项列表作为函数参数的类对象实现运算符 [] 的示例
- C++派生类中的纯虚函数实现
- 什么更有效率?在重载函数中或通过在基类函数中检查对象类型来实现
- 如何根据参数化类型的特定成员的类型对模板类函数进行不同的实现
- 如何让成员函数实现依赖于类的模板参数?
- 如何在模板容器类中实现复制构造函数和赋值运算符
- 使用可变参数模板函数在类周围实现基于 pImpl 的包装器
- 如何在C++中正确表达具有相同实现的两个派生类函数?
- 我们如何将Ostream函数作为类的成员函数实现,而不是作为朋友函数,以便我可以用作虚拟函数
- 如果未实现虚函数,则大多数派生类无法编译,但如果一个基类未实现虚函数,则可以编译
- 如何避免类函数的多个实现
- 从类模板实现纯虚函数 - 参数类型
- 如何使用继承(抽象基类)实现移动构造函数和移动赋值运算符
- 遇到C++方形类的问题. 成员函数实现和声明
- 将类函数实现从 .h 移动到.cpp过程