所以这是简化的问题,假设我们有两种类型
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版本。
答案 0 :(得分:1)
有几种方法可以解决这个问题。
最简单的方法是使用正常的重载分辨率:
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)>();
}
};
答案 1 :(得分:1)
您可以使用一些函数声明(在这种情况下不需要定义),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;
}
}
答案 2 :(得分:0)
您可以使用一些oveload函数来运行不同的代码,比如说你有int func (shape 2D x)
和int func (shape3D x)
,所以在method1
中调用func (T.position)
,编译器会帮助你解决电话。