出于性能原因,我使用带有枚举的模板化类,而不是继承继承(这不是一种选择)。
在这一点上,我有这样的事情:
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
}
现在,如果为defineT
调用了不兼容的构造函数,我会使用大量烦人的ifs / switches和上升异常T
。
我想要使用std::enable_if
或等效的方法来防止在构造函数上引发异常并在编译时检测此类错误。
我已经尝试了很多堆栈溢出和外部站点的std::enable_if
示例,但是我几乎无法理解我在做什么,而且我总是以编译错误告终。
在此先感谢您,并很抱歉提出一个可能很简单的问题。我对模板没有知识。
环境:Linux GCC 8和c ++ 14限制:在没有虚拟方法的情况下可实现最佳性能。
我想要的是使用std :: enable_if或等效方法来防止在构造函数上引发异常并在编译时检测此类错误。
我已经尝试了很多堆栈溢出和外部站点的
std::enable_if
示例,但是我几乎无法理解我在做什么,而且我总是以编译错误告终。
问题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
isB
或时启用第二个构造函数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
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句