将枚举值与SFINAE结合使用

Teitoku42

我已经熟悉SFINAE,以及如何将其用于基于传递的类型(通过使用std :: enable_if)来启用特定模板。但是,我最近开始在一个项目中进行以下操作:使用SFINAE时,根据提供的枚举VALUE创建类专门化。现在,我知道考虑到我之前做过的事情,可以基于枚举值进行专业化(像这样):

enum Specifier
{
   One,
   Two,
   Three
}

template <Specifier>
class Foo
{
public:
   void Bar();
}

template<>
void Foo<Specifier::One>::Bar()
{
}

但是,现在我想使用SFINAEBar()对多个枚举值使用特定的特殊化像这样:

template <Specifier Type>
class Foo
{
public:
   template <typename std::enable_if<Type == Specifier::Two || Type == Specifier::One, void>::type> 
   void Bar();

   template <typename std::enable_if<Type == Specifier::Three, void>::type> 
   void Bar();
}

知道这是否可能吗,如果可以,我将如何去做?

dfrib

C ++ 17:constexpr如果

从C ++ 17起,您可以使用单个成员函数重载(而不是通过SFINAE出现或不存在的几个重载),其主体在以下情况下利用constexpr:

#include <iostream>

enum class Specifier { One, Two, Three };

template <Specifier S> class Foo {
public:
  static constexpr int bar() {
    if constexpr ((S == Specifier::One) || (S == Specifier::Two)) {
      return 12;
    } else if constexpr (S == Specifier::Three) {
      return 3;
    }
  }
};

int main() {
  std::cout << Foo<Specifier::One>::bar() << "\n" // 12
            << Foo<Specifier::Two>::bar() << "\n" // 12
            << Foo<Specifier::Three>::bar();      // 3
}

C ++ 11:SFINAE和std::enable_if_t)(C ++ 14)

同样,您也可以使用SFINAE,要求将非模板成员函数设为带有虚拟模板参数的成员函数模板,因为SFINAE需要在每个函数声明中应用于从属名称,并应用于类模板(类型或(非类型)参数在非模板成员函数的声明中自然不是从属名称

template <Specifier S> class Foo {
public:
  template <Specifier S_ = S,
            std::enable_if_t<(S_ == Specifier::One) || (S_ == Specifier::Two)>
                * = nullptr>
  static constexpr int bar() {
    return 12;
  }

  template <Specifier S_ = S,
            std::enable_if_t<(S_ == Specifier::Three)> * = nullptr>
  static constexpr int bar() {
    return 3;
  }
};

请注意,上面的示例使用了std::enable_if_tC ++ 14中引入的辅助别名模板如果使用的是C ++ 11,则需要使用typename std::enable_if<..>::type

此外,请注意,由于我们必须对成员函数进行模板化,滥用用户可以选择覆盖(虚拟)非类型模板参数的默认模板参数S_

Foo<Specifier::One>::bar<Specifier::Three>();  // 3

因此,我们可能希望std::enable_if_t为每个重载谓词添加一个附加AND条件(S_ == S) && (... predicate as above)正如我们将在后面的部分中看到的那样,这在C ++ 20中不再是问题,因为我们可以避免将非模板成员函数仅用作应用SFINAE的模板。

使用专业化而不是重载的替代方法

正如我在以下针对该问题的后续问题的答案中所显示的那样,您还可以在专门化的模板参数列表中(部分专业化的类模板)应用SFINAE:

template <Specifier, typename = void> struct Foo {
  static constexpr int bar() { return 1; }  // default
};

template <Specifier S>
struct Foo<S,
           std::enable_if_t<(S == Specifier::One) || (S == Specifier::Two)>> {
  static constexpr int bar() { return 12; }
};

C ++ 20:类模板的非模板成员函数可以使用require-clause:s

从C ++ 20开始,您可以使用尾随需求子句对每个重载进行互斥约束,从而重载和约束类模板的非模板成员函数

template <Specifier S> class Foo {
public:
  static constexpr int bar() requires((S == Specifier::One) ||
                                      (S == Specifier::Two)) {
    return 12;
  }

  static constexpr int bar() requires(S == Specifier::Three) { return 3; }
};

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

将枚举值与SFINAE结合使用

来自分类Dev

将枚举值与位标记结合

来自分类Dev

将 Eval() 与检查值的存在结合使用

来自分类Dev

将XPath与条件结合使用以从XML获取数组值

来自分类Dev

使用自定义序列将枚举值与枚举值绑定

来自分类Dev

结合使用switch语句和枚举

来自分类Dev

如何使用Hibernate将枚举值保存到DB?

来自分类Dev

使用枚举键将值添加到Swift字典

来自分类Dev

使用枚举键将值添加到Swift字典

来自分类Dev

使用@JsonProperty将Searialing枚举为int值

来自分类Dev

使用MarkupExtension将ComboBox绑定到枚举值的集合

来自分类Dev

使用枚举值

来自分类Dev

如何使用枚举值?

来自分类Dev

使用枚举值

来自分类Dev

WPF C#-将枚举绑定到ComboBox,但不使用所有枚举值

来自分类Dev

结合SFINAE的静态过载

来自分类Dev

将依赖值注入枚举

来自分类Dev

如何在不指定枚举的情况下将 SFINAE 用于枚举?

来自分类Dev

将GHC与NVCC结合使用

来自分类Dev

将Swagger与Flask结合使用

来自分类Dev

将PowerMock与Spock结合使用

来自分类Dev

Python将'OR与Regex结合使用

来自分类Dev

将MEF与MVC结合使用

来自分类Dev

将Appcache与CodeIgniter结合使用

来自分类Dev

将PouchDB与MongoDB结合使用

来自分类Dev

将AES与AndroidKeyStore结合使用

来自分类Dev

将Hangfire与ServiceStack结合使用

来自分类Dev

将jQuery与Jade结合使用

来自分类Dev

将CQRS与DDD结合使用?