组类模板特化

时间:2014-07-08 09:18:24

标签: c++ templates c++11 traits enable-if

是否有针对某些类型对类模板专精进行分组的技术/最佳风格?

一个例子:假设我有一个类模板Foo,我需要让它专门用于排版

A = { Line, Ray }

以另一种方式为排版B

B = { Linestring, Curve }

到目前为止我正在做的事情:(该技术也为函数提供了here

#include <iostream>
#include <type_traits>
using namespace std;

// 1st group
struct Line    {};
struct Ray     {};
// 2nd group 
struct Curve      {};
struct Linestring {};

template<typename T, typename Groupper=void>
struct Foo
{ enum { val = 0 }; };

// specialization for the 1st group 
template<typename T>
struct Foo<T, typename enable_if<
    is_same<T, Line>::value ||
    is_same<T, Ray>::value
>::type>
{
    enum { val = 1 };
};

// specialization for the 2nd group 
template<typename T>
struct Foo<T, typename enable_if<
    is_same<T, Curve>::value ||
    is_same<T, Linestring>::value
>::type>
{
    enum { val = 2 };
};

int main() 
{
    cout << Foo<Line>::val << endl;
    cout << Foo<Curve>::val << endl;
    return 0;
}

额外的辅助结构enable_for会缩短代码(并允许直接编写接受的类型)。任何其他建议,更正?这不应该减少努力吗?

2 个答案:

答案 0 :(得分:13)

您也可以使用自己的特性而不使用enable_if

// Traits

template <class T>
struct group_number : std::integral_constant<int, 0> {};

template <>
struct group_number<Line> : std::integral_constant<int, 1> {};

template <>
struct group_number<Ray> : std::integral_constant<int, 1> {};

template <>
struct group_number<Linestring> : std::integral_constant<int, 2> {};

template <>
struct group_number<Curve> : std::integral_constant<int, 2> {};


// Foo

template <class T, int Group = group_number<T>::value>
class Foo
{
  //::: whatever
};

template <class T>
class Foo<T, 1>
{
  //::: whatever for group 1
};

template <class T>
class Foo<T, 2>
{
  //::: whatever for group 2
};

这样做的好处是可以自动确保每种类型最多只有一个组。

答案 1 :(得分:11)

使用两种新类型特征的额外间接级别:

template<class T>
struct is_from_group1: std::false_type {};

template<>
struct is_from_group1<Line>: std::true_type {};

template<>
struct is_from_group1<Ray>: std::true_type {};

template<class T>
struct is_from_group2: std::false_type {};

template<>
struct is_from_group2<Curve>: std::true_type {};

template<>
struct is_from_group2<Linestring>: std::true_type {};

然后对这些类型特征执行enable_if

// specialization for the 1st group 
template<typename T>
struct Foo<T, typename enable_if<
    is_from_group1<T>::value
>::type>
{
    enum { val = 1 };
};

// specialization for the 2nd group 
template<typename T>
struct Foo<T, typename enable_if<
    is_from_group2<T>::value
>::type>
{
    enum { val = 2 };
};

请注意,您仍然需要确保没有向两个组添加用户定义的类,否则您将会产生歧义。您可以使用@ Angew的解决方案从编号组派生,使用std::integral_constant<int, N>获取组编号N。或者,如果这些组在逻辑上不是唯一的,您可以在enable_if内添加一个额外的条件来防范这种情况。