类模板,独立于其参数的排列

Vah*_*yan 5 c++ class-template c++11

考虑一个类模板和辅助枚举类,定义如下:

enum class Color {Red, Green, Blue}
enum class ShowAxes {False, True}
enum class ShowLabels {False, True}

template< Color, ShowAxes, ShowLabels >
class A
{......};
Run Code Online (Sandbox Code Playgroud)

问题是,如何重新定义A类,它将独立于其论点的排列.我使用Dev C++,它支持C++ 11.

[编辑]

例如,新版本的A应该支持

A< Color::Red, ShowAxes::True, ShowLabels::True >
A< Color::Red, ShowLabels::True, ShowAxes::True >
A< ShowAxes::True, Color::Red, ShowLabels::True >
A< ShowLabels::True, Color::Red, ShowAxes::True >
A< ShowLabels::True, Color::Red, ShowAxes::True >
A< ShowAxes::True, Color::Red, ShowLabels::True >
Run Code Online (Sandbox Code Playgroud)

版本,并且它们都是相同的,即它们生成相同的类.

T.C*_*.C. 5

您当前的界面无法使用非类型参数.

您可以改为使用类型参数并将值包装在std::integral_constant:

template<class X, class Y, class Z>
class A { /* stuff */ };

// use as:
A<std::integral_constant<Color, Color::Red>,
  std::integral_constant<ShowAxes, ShowAxes::True>,
  std::integral_constant<ShowLabels, ShowLabels::True>> a;
Run Code Online (Sandbox Code Playgroud)

这是相当冗长的,所以你可以考虑编写一个宏:

#define AS_IC(Value) std::integral_constant<decltype(Value), Value>
Run Code Online (Sandbox Code Playgroud)

并重写为

A<AS_IC(Color::Red), AS_IC(ShowAxes::True), AS_IC(ShowLabels::True)> a;
Run Code Online (Sandbox Code Playgroud)

integral_constants 列表中提取所需类型的值非常简单:

template<class Result, class...>
struct extract;

template<class Result, Result Value, class... Tail>
struct extract<Result, std::integral_constant<Result, Value>, Tail...> : std::integral_constant<Result, Value> {};

template<class Result, class Head, class... Tail>
struct extract<Result, Head, Tail...> : extract<Result, Tail...> {};
Run Code Online (Sandbox Code Playgroud)

那你可以做

// inside the definition of A
static constexpr Color col = extract<Color, X, Y, Z>::value;
Run Code Online (Sandbox Code Playgroud)

演示.

但是,这不会生成相同的类,但是您可以创建一个类模板A_impl,其行为A与非类型参数类似,并且包含实际实现,然后创建A别名模板:

template< Color, ShowAxes, ShowLabels >
class A_impl
{/* stuff */};

template<class X, class Y, class Z>
using A = A_impl<extract<Color, X, Y, Z>::value,
                 extract<ShowAxes, X, Y, Z>::value,
                 extract<ShowLabels, X, Y, Z>::value>;
Run Code Online (Sandbox Code Playgroud)

现在给出

A<AS_IC(Color::Red), AS_IC(ShowAxes::True), AS_IC(ShowLabels::True)> a;
A<AS_IC(Color::Red), AS_IC(ShowLabels::True), AS_IC(ShowAxes::True)> b;
Run Code Online (Sandbox Code Playgroud)

ab具有相同的类型.演示.

或者,您也可以使用decltype和重载函数模板,但这需要为每种可能的类型顺序添加函数模板声明:

template< Color c, ShowAxes a, ShowLabels l>
A<c,a,l> A_of();

template< ShowAxes a, ShowLabels l, Color c>
A<c,a,l> A_of();

// etc.

decltype(A_of<Color::Red, ShowAxes::True, ShowLabels::True>()) a1;
decltype(A_of<ShowAxes::True, ShowLabels::True, Color::Red>()) a2;
Run Code Online (Sandbox Code Playgroud)