组合多个类模板专用化
Combine multiple class template specializations
给定下面的示例,压缩模板专用化的最佳方法是什么,以便一两条指令足以定义所有特殊值?也许是变种?
enum class PositiveDigit // Not necessarily sequential
{ One=1, Two, Three, Four, Five, Six, Seven, Eight, Nine };
// Base class template
template <std::underlying_type_t<PositiveDigit>>
struct IsNum
{ static constexpr bool aPrimeDigit = false; };
// Specialized class templates to define which positive digits are prime
// HOW TO BEST COMBINE/CONDENSE THESE? VARIADIC?? Ideally, something like:
// template <PositiveDigit::Two, PositiveDigit::Three, ……> …… OR,
// template <> …… (PositiveDigit::Two, PositiveDigit::Three, ……) …… OR??
template <>
struct IsNum<static_cast<std::underlying_type_t<PositiveDigit>>(PositiveDigit::Two)>
{ static constexpr bool aPrimeDigit = true; };
template <>
struct IsNum<static_cast<std::underlying_type_t<PositiveDigit>>(PositiveDigit::Three)>
{ static constexpr bool aPrimeDigit = true; };
template <>
struct IsNum<static_cast<std::underlying_type_t<PositiveDigit>>(PositiveDigit::Five)>
{ static constexpr bool aPrimeDigit = true; };
template <>
struct IsNum<static_cast<std::underlying_type_t<PositiveDigit>>(PositiveDigit::Seven)>
{ static constexpr bool aPrimeDigit = true; };
int main() {
// Note: It's perfectly okay to pass integers beyond the range of the
// enum class, they'll simply provide a false result
IsNum<-5>::aPrimeDigit; // false
IsNum<13>::aPrimeDigit; // false
IsNum< 7>::aPrimeDigit; // true!
}
请假设enum
必须保持强类型。现实世界的问题有很大的enum class
,许多潜在的专业,与数字或素数无关;这只是一个简单的例子。
这些类似的问题似乎并不能解决手头的问题(除非我遗漏了什么(:
- 具有多个可变参数模板的模板专用化
- 组类模板专业化
- SFINAE 和部分类模板专业化
只是为了取笑可变参数模板,我提出了几个解决方案。
它们都基于一个constexpr
函数,该函数表示值是否在模板可变参数列表中(如 aschepler 的答案中所value_in_list
,但这也适用于 C++14(
template <typename T, T ... ts>
constexpr bool isInList (T const & t0)
{
using unused = bool[];
bool ret { false };
(void)unused { false, ret |= t0 == ts... };
return ret;
}
第一个与 aschepler 的解决方案 (+1( 非常相似,并且不使用模板专用化。
template <std::underlying_type_t<PositiveDigit> I>
struct IsNum1
{
static constexpr bool aPrimeDigit
= isInList<PositiveDigit, PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven>
(static_cast<PositiveDigit>(I));
};
在我看来,这是更简单的,但如果你真的(真的!(想通过模板专业化,你可以写一些东西如下
template <std::underlying_type_t<PositiveDigit>, typename = std::true_type>
struct IsNum2
{ static constexpr bool aPrimeDigit = false; };
template <std::underlying_type_t<PositiveDigit> I>
struct IsNum2<I, std::integral_constant<bool, isInList<
PositiveDigit, PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven>
(static_cast<PositiveDigit>(I))>>
{ static constexpr bool aPrimeDigit = true; };
以下是完整的编译示例
#include <type_traits>
enum class PositiveDigit
{ Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine };
template <typename T, T ... ts>
constexpr bool isInList (T const & t0)
{
using unused = bool[];
bool ret { false };
(void)unused { false, ret |= t0 == ts... };
return ret;
}
template <std::underlying_type_t<PositiveDigit> I>
struct IsNum1
{
static constexpr bool aPrimeDigit
= isInList<PositiveDigit, PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven>
(static_cast<PositiveDigit>(I));
};
template <std::underlying_type_t<PositiveDigit>, typename = std::true_type>
struct IsNum2
{ static constexpr bool aPrimeDigit = false; };
template <std::underlying_type_t<PositiveDigit> I>
struct IsNum2<I, std::integral_constant<bool, isInList<
PositiveDigit, PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven>
(static_cast<PositiveDigit>(I))>>
{ static constexpr bool aPrimeDigit = true; };
int main ()
{
static_assert( false == IsNum1<-5>::aPrimeDigit, "!" );
static_assert( false == IsNum1<13>::aPrimeDigit, "!" );
static_assert( true == IsNum1< 7>::aPrimeDigit, "!" );
static_assert( false == IsNum2<-5>::aPrimeDigit, "!" );
static_assert( false == IsNum2<13>::aPrimeDigit, "!" );
static_assert( true == IsNum2< 7>::aPrimeDigit, "!" );
}
你在寻找这样的东西吗?
C++17:
#include <type_traits>
template <auto Value, decltype(Value)... List>
struct value_in_list
: public std::disjunction<std::bool_constant<Value==List>...> {};
template <std::underlying_type_t<PositiveDigit> N>
struct IsNum
{
static constexpr bool aPrimeDigit =
value_in_list<static_cast<PositiveDigit>(N),
PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven
>::value;
};
或C++14:
#include <type_traits>
template <typename T, T Value, T... List>
struct value_in_list;
// Base case 1: Value is not in an empty list.
template <typename T, T Value>
struct value_in_list<T, Value> : public std::false_type {};
// Base case 2: Value is in a list that starts with Value.
template <typename T, T Value, T... Rest>
struct value_in_list<T, Value, Value, Rest...>
: public std::true_type {};
// Recursion case: If a non-empty list does not start with Value,
// Value is in the list if and only if it's in the list with the
// first element removed.
template <typename T, T Value, T First, T... Rest>
struct value_in_list<T, Value, First, Rest...>
: public value_in_list<T, Value, Rest...> {};
template <std::underlying_type_t<PositiveDigit> N>
struct IsNum
{
static constexpr bool aPrimeDigit =
value_in_list<PositiveDigit, static_cast<PositiveDigit>(N),
PositiveDigit::Two, PositiveDigit::Three,
PositiveDigit::Five, PositiveDigit::Seven
>::value;
};
相关文章:
- .cpp和.h文件中的模板专用化声明
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 调用专用模板时出错"no matching function for call to [...]"
- 可组合的lambda/std::函数与std::可选
- 模板专用化(按容器):value_type
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 混合组合和继承的C++问题
- 我需要将多个函数组合为一个函数
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 通过组合不同的类型来创建唯一的id
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 模板元编程:如何将参数包组合成新的参数包
- 静态数据成员模板专用化的实例化点在哪里
- 检查向量是否具有所有可能的字符组合
- 特征 3 类的模板专用化
- Visual Studio 2017 不允许我创建 C++ 专用模板
- 如何在加密++中将两个源组合成新的源
- 根中的组合
- 组合多个类模板专用化
- C++按类型组与基本类型组合的模板专用化