如何部分特化 class 模板非类型参数
How can I partially specialize class template non-type parameters
我的问题很基础。我试图给自己一个方便的 class 模板实例化,它可以做一些数学上直观的事情。我希望能够通过将其实例化为 Q<31>
来实例化一个名为 Q<0,31>
的 class。根据cppreference.com,这个should be possible:
template<class T>
class A<int, T*, 5> {}; // #3: partial specialization where T1 is int, I is 5,
// and T2 is a pointer
但是当我尝试这个时:
template< unsigned integral, unsigned fractional >
class Q: public Signed<integral + fractional + 1u> {};
// There's a shorthand for Q notation where you don't specify the number of integer bits, and it's assumed to be 0
template< unsigned fractional > class Q<0u, fractional>: public Signed<fractional + 1> {};
static_assert( std::is_same< Q<31>, Q<0,31> >::value, "Partial specialization should be equivalent to no integer component");
然后我收到一条错误消息,说我没有传递足够的模板参数
专业化不是重载。它们是模式匹配。
没有办法"overload"你想要的模板,缺少魔法值。
template< unsigned fractional >
class Q<0u, fractional>
这只是模式匹配。
你的论点是总是
template< unsigned integral, unsigned fractional >
class Q
并且当某人通过 0u
达到 integral
时,您的专长匹配。所以它匹配
Q<0u, fractional>
它不匹配
Q<fractional>
现在,如前所述,您可以使用魔法值来做到这一点:
template< unsigned integral, unsigned fractional=-1 >
class Q
template< unsigned fractional >
class Q<fractional, -1>:Q<0u, fractional> {}
但如果有人手动通过 -1
,也会发生这种情况。
在 c++20 中,您将能够将用户定义的类型作为模板非类型模板参数,因此您可以执行以下操作:
template< unsigned A, optional<unsigned> B = {} >
class Q;
template< unsigned integral, unsigned fractional >
class Q< integral, optional<unsigned>(fractional) > // 2 arg case
template< unsigned fractional >
class Q< fractional, nullopt >:Q<0u, fractional> {}; // 1 arg case
但这还没有。
您无法按照您想要的方式实现它,因为正如已经说过的那样,它不会过载,但是使用具有部分特化的别名模板是可能的:
template<int, int B>
struct Q {};
template<int B>
using Q0 = Q<0,B>;
在您的代码中
static_assert( std::is_same< Q0<31>, Q<0,31> >::value, "Partial specialization should be equivalent to no integer component");
这将编译没有错误
我的问题很基础。我试图给自己一个方便的 class 模板实例化,它可以做一些数学上直观的事情。我希望能够通过将其实例化为 Q<31>
来实例化一个名为 Q<0,31>
的 class。根据cppreference.com,这个should be possible:
template<class T>
class A<int, T*, 5> {}; // #3: partial specialization where T1 is int, I is 5,
// and T2 is a pointer
但是当我尝试这个时:
template< unsigned integral, unsigned fractional >
class Q: public Signed<integral + fractional + 1u> {};
// There's a shorthand for Q notation where you don't specify the number of integer bits, and it's assumed to be 0
template< unsigned fractional > class Q<0u, fractional>: public Signed<fractional + 1> {};
static_assert( std::is_same< Q<31>, Q<0,31> >::value, "Partial specialization should be equivalent to no integer component");
然后我收到一条错误消息,说我没有传递足够的模板参数
专业化不是重载。它们是模式匹配。
没有办法"overload"你想要的模板,缺少魔法值。
template< unsigned fractional >
class Q<0u, fractional>
这只是模式匹配。
你的论点是总是
template< unsigned integral, unsigned fractional >
class Q
并且当某人通过 0u
达到 integral
时,您的专长匹配。所以它匹配
Q<0u, fractional>
它不匹配
Q<fractional>
现在,如前所述,您可以使用魔法值来做到这一点:
template< unsigned integral, unsigned fractional=-1 >
class Q
template< unsigned fractional >
class Q<fractional, -1>:Q<0u, fractional> {}
但如果有人手动通过 -1
,也会发生这种情况。
在 c++20 中,您将能够将用户定义的类型作为模板非类型模板参数,因此您可以执行以下操作:
template< unsigned A, optional<unsigned> B = {} >
class Q;
template< unsigned integral, unsigned fractional >
class Q< integral, optional<unsigned>(fractional) > // 2 arg case
template< unsigned fractional >
class Q< fractional, nullopt >:Q<0u, fractional> {}; // 1 arg case
但这还没有。
您无法按照您想要的方式实现它,因为正如已经说过的那样,它不会过载,但是使用具有部分特化的别名模板是可能的:
template<int, int B>
struct Q {};
template<int B>
using Q0 = Q<0,B>;
在您的代码中
static_assert( std::is_same< Q0<31>, Q<0,31> >::value, "Partial specialization should be equivalent to no integer component");
这将编译没有错误