简体   繁体   English

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

[英]Using C++ std::enable_if with a normal function?

let's say I have an enumeration: 假设我有一个枚举:

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

And a function check(vals x) which returns a boolean indicating whether the val is in a specific subset of values in vals . 并且函数check(vals x)返回一个布尔值,指示val是否在vals中的特定值子集中。

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

I want to use this function as a condition for the enable_if (the function, as you can see, it's not a function depending on the runtime), to let the users use only those values with the class template. 我想使用这个函数作为enable_if的条件(正如你所看到的那样,它不是一个函数,取决于运行时),让用户只使用带有类模板的那些值。

class MyClass<vals v> {

}

PS: I need the template to make specializations for a method of the class, depending on the template value. PS:我需要模板来为类的方法进行特化,具体取决于模板值。

In C++14, just declare the function constexpr and keep the implementation as is. 在C ++ 14中,只需声明函数constexpr并保持实现不变。

In C+11 you need to change it to a single return statement: 在C + 11中,您需要将其更改为单个return语句:

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

You don't need neither a function nor enable_if to do that. 您既不需要函数也不需要enable_if来执行此操作。
Here is an example: 这是一个例子:

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;
}

This solution has actually a problem: MyClass<vals::Val2, true> ok; 这个解决方案实际上有一个问题: MyClass<vals::Val2, true> ok; is a valid statement. 是一个有效的声明。
Anyway, if it fits well mostly depends on the real problem. 无论如何,如果它适合,主要取决于真正的问题。

If you want to use enable_if you can do this: 如果要使用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;
}

Another solution would be using a static_assert : 另一个解决方案是使用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;
}

And so on, there exist a bunch of alternatives that does not require a constexpr ed function. 等等,存在许多不需要constexpr功能的替代方案。

Otherwise let the function be constexpr as mentioned by @nm and that's all. 否则,让函数成为@nm所提及的constexpr ,这就是全部。

Thanks for the answer guys. 谢谢你的回答。 I found another solution that could be even better for my problem. 我找到了另一种解决方案,可能对我的问题更好。 Since I have to implement a specialized method for all of the supported values, I can even put an assertion in the unspecialized method. 由于我必须为所有支持的值实现专门的方法,我甚至可以在非专用方法中设置断言。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM