c++ - 在某些枚举模板情况下启用类构造函数

标签 c++ templates c++14 sfinae enable-if

出于性能原因,我使用带有枚举的模板化类而不是继承继承(这不是一个选项)。

此时我有类似的东西:

typedef enum { A, B, C, D } QueueType;

template <QueueType T> class Queue {
    Queue(int a){...} // only usable when T = A
    Queue(unsigned a, unsigned b){...} // only usable when T = B || T = C
    Queue(somestruct z){...} // only usable when T = B || T = C
    //other constructors
}

现在,如果为已定义的 T 调用不兼容的构造函数,我会在 T 上使用大量的 ifs/switches 和上升的异常。

我想要的是使用 std::enable_if 或等价物来防止在构造函数上抛出异常并在编译时检测此类错误。

我已经尝试过很多堆栈溢出和外国站点 std::enable_if 示例,但我几乎无法理解我到底在做什么,而且我总是以编译错误告终。

提前致谢,很抱歉提出一个可能回答不多的问题。我对模板一窍不通。

环境:Linux GCC 8 和 c++14 限制:没有虚拟方法的最大性能。

最佳答案

What I want is to use std::enable_if or equivalent to prevent throwing exceptions on constructor and detect on compilation time such kind of errors.

I've tried many stack-overflows and foreign sites std::enable_if examples, but I can barely understand what I'm really doing and I always end on a compilation error.

std::enable_if(和 SFINAE,更普遍)的问题是它只检查模板参数。因此可以启用/禁用一个完整的类,通过类的模板参数进行测试,但不能启用/禁用单个方法,通过类的模板参数进行测试。

如果您希望 SFINAE 启用/禁用一个方法(比如您的构造函数),您必须将其设为模板方法并测试该方法本身的模板参数。

所以你不能这样写

template <typename = std::enable_if_t<T == A>>
Queue (int)
 { } // only usable when T = A

因为 T 是类的模板参数,而不是构造函数的模板参数。

但是有一个技巧:你可以为模板参数使用默认值/类型;所以下面的代码有效

template <QueueType U = T, typename = std::enable_if_t<U == A>>
Queue (int)
 { } // only usable when T = A 

因为检查了作为构造函数模板参数的值 U

要仅在TBC时启用第二个构造函数,您可以这样写

template <QueueType U = T, typename = std::enable_if_t<(U == B) || (U == C)>> 
Queue (unsigned, unsigned)
 { } // only usable when T = B || T = C

下面是一个完整的编译示例

#include <type_traits>

typedef enum { A, B, C, D } QueueType;

template <QueueType T>
struct Queue
 {
   template <QueueType U = T, typename = std::enable_if_t<U == A>>
   Queue (int)
    { } // only usable when T = A

   template <QueueType U = T, typename = std::enable_if_t<(U == B) || (U == C)>>
   Queue (unsigned, unsigned)
    { } // only usable when T = B || T = C
 };

int main()
 {
   Queue<A>  qa0{1};         // compile
   //Queue<A>  qa1{1u, 2u};  // compilation error

   // Queue<B>  qb0{1};      // compilation error
   Queue<B>  qb1{1u, 2u};    // compile

   // Queue<C>  qc0{1};      // compilation error
   Queue<C>  qc1{1u, 2u};    // compile

   // Queue<D>  qd0{1};      // compilation error
   // Queue<D>  qd1{1u, 2u}; // compilation error
 }

关于c++ - 在某些枚举模板情况下启用类构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53175111/

相关文章:

c++ - 如何提高内存使用性能?

string - 在模板字符串中求值

c++ - 允许在模板函数中对浮点类型进行位移的变通方法

c++ - Clang 3.7.0 提示类不是文字,因为它不是聚合并且没有 constexpr 构造函数

c++ - 如果基类受到保护,则无法访问派生类中的转换

c++ - 输入7个字母单词,输出7位数电话号码

c++ - 确保相机位置始终位于屏幕中心?

c++ std::vector<> vs new[] 性能

c++ - 如何在 Sublime Text 上的 Windows/Cygwin 上构建 yaml-cpp?

c++ - 将 `std::sort` 与模板类中的成员函数一起使用