出于性能原因,我使用带有枚举的模板化类而不是继承继承(这不是一个选项)。
此时我有类似的东西:
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
。
要仅在T
为B
或C
时启用第二个构造函数,您可以这样写
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/