使用C ++ std :: enable_if和普通函数?

时间:2016-06-07 17:54:08

标签: c++ templates

让我们说我有一个枚举:

typedef enum {
  Val1,
  Val2,
  Val3,
  Val4
} vals;

一个函数check(vals x),它返回一个布尔值,表示val是否在vals的特定值子集中。

bool check(vals x) {
  switch(x) {
  case Val1:
  case Val3:
    return true;
  }
  return false;
}

我希望将此函数用作enable_if的条件(正如您所见,该函数不是取决于运行时的函数),让用户只使用这些值使用课程模板。

class MyClass<vals v> {

}

PS:我需要模板来为类的方法进行特化,具体取决于模板值。

3 个答案:

答案 0 :(得分:6)

在C ++ 14中,只需声明函数constexpr并保持实现不变。

在C + 11中,您需要将其更改为单个return语句:

constexpr bool check(vals x) {
    return x == Val1 || x == Val3;
}

答案 1 :(得分:4)

你既不需要功能也不需要enable_if这样做 这是一个例子:

enum class vals {
    Val1,
    Val2,
    Val3,
    Val4
};

template<vals v, bool = (v == vals::Val1 || v == vals::Val3)>
class MyClass;

template<vals v>
class MyClass<v, true> { };

int main() {
    MyClass<vals::Val1> ok;
    // MyClass<vals::Val2> ko;
}

此解决方案实际上存在问题:MyClass<vals::Val2, true> ok;是一个有效的声明 无论如何,如果它很适合,主要取决于真正的问题。

如果您想使用enable_if,可以执行此操作:

#include<type_traits>

enum class vals {
    Val1,
    Val2,
    Val3,
    Val4
};

template<vals v, std::enable_if_t<(v == vals::Val1 || v == vals::Val3)>* = nullptr>
class MyClass { };

int main() {
    MyClass<vals::Val1> ok;
    // MyClass<vals::Val2> ko;
}

另一种解决方案是使用static_assert

enum class vals {
    Val1,
    Val2,
    Val3,
    Val4
};

template<vals v>
class MyClass {
    static_assert((v == vals::Val1 || v == vals::Val3), "!");
};

int main() {
    MyClass<vals::Val1> ok;
    // MyClass<vals::Val2> ko;
}

依此类推,存在许多不需要constexpr ed函数的替代方案。

否则让@ n.m提到的函数为constexpr。这就是全部。

答案 2 :(得分:0)

谢谢你的回答。 我找到了另一种解决方案,可能对我的问题更好。 由于我必须为所有支持的值实现一个专门的方法,我甚至可以在非专用方法中加入一个断言。

template<vals v>
MyClass<v>::method() {
  assert(check(v) && "Unsupported value!");
}

template<>
MyClass<Val1>::method() {
   // do it!
}