具有基于类型的不同定义的模板化函数

时间:2019-07-28 13:55:25

标签: c++ templates operator-overloading

假设我们有具有不同成员类型和数量的不同类(结构)。为了便于说明,它们是2D和3D向量。

struct i2 { 
    int a, b; 
    i(int a, int b): a(a), b(b) {}
};

struct f2 { 
    float a, b;
    f(float a, float b): a(a), b(b) {}
};

struct i3 { 
    int a, b, c; 
    i(int a, int b): a(a), b(b), c(c) {}
};

struct f3 { 
    float a, b, c;
    f(float a, float b): a(a), b(b), c(c) {}
};

我想以模板方式实现一些相关功能。在课外说一个加法运算符,例如

template<class Type> Type operator+(const Type& P, const& Type Q)
  { return Type(P.a + Q.b, P.a + P.b); }

很明显,这不适用于3D变体,这需要

template<class Type> Type operator+(const Type& P, const Type& Q)
  { return Type(P.a + Q.a, P.b + P.b, P.c + Q.c); }

在没有众多显式专业的情况下,是否有一种很好的方法来实现这一目标?如果它使用高级C ++功能,将支持该功能的最低版本是什么?

换句话说,是否存在一种编译时机制来根据参数类型有条件地实例化模板?

请注意,我希望初始类保持非模板状态,因为这会在设计中引入其他问题。

2 个答案:

答案 0 :(得分:1)

一旦拥有特质,就可以使用SFINAE。

特征可以在任何版本的C ++中完成,即使使用更新的版本会更容易。

根据您要如何定义特征,可以使用类似的

template <typename T>
using is_2d_vector = std::disjunction_t<std::is_same<T, i2>, std::is_same<T, f2>>;

template <typename T>
using is_3d_vector = std::disjunction_t<std::is_same<T, i3>, std::is_same<T, f3>>;

// possible alternatives include detection of T::a, T::b, T::c

template<class T, std::enable_if_t<is_2d_vector<T>, int> = 0>
T operator+(const T& lhs, const T& rhs)
{ return T(lhs.a + rhs.a, lhs.b + rhs.b); }

template<class T, std::enable_if_t<is_3d_vector<T>, int> = 0>
T operator+(const T& lhs, const T& rhs)
{ return T(lhs.a + rhs.a, lhs.b + rhs.b, lhs.c + rhs.c); }

但是最初拥有模板类似乎更简单:

template <typename T>
struct T2 { 
    T a, b;
    T2(T a, T b): a(a), b(b) {}

    friend operator +(const T2& lhs, const T2& rhs)
    { return T(lhs.a + rhs.a, lhs.b + rhs.b); }
};

template <typename T>
struct T3 { 
    T a, b, c; 
    T3(T a, T b, T c): a(a), b(b), c(c) {}

    friend operator +(const T2& lhs, const T2& rhs)
    { return T(lhs.a + rhs.a, lhs.b + rhs.b, lhs.c + rhs.c); }
};

using i2 = T2<int>;
using i3 = T3<int>;
using f2 = T2<float>;
using f3 = T3<float>;

答案 1 :(得分:0)

我认为做到这一点的一种方法是使用编译时(静态)反射。在线上有很多文章,其中有两篇,https://medium.com/@vesko.karaganev/compile-time-reflection-in-c-17-55c14ee8106bhttps://Frly.sexy/post/basic-reflection-in-pure-cpp17

但是我不确定这是解决问题的最佳方法,因为更好的答案将需要更多具体细节。