以下面的示例为例,凝聚模板专业化的最佳方法是什么,以便一个或两个指令足以定义所有特殊值?可变参数的,也许吗?
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
很大,潜在的专业领域很多,与数字或质数无关。这只是一个简单的例子。
这些类似的问题似乎无法解决当前的问题(除非我遗漏了一些东西):
答案 0 :(得分:1)
您是否正在寻找类似的东西?
C ++ 17:
import std.stdio;
class CAdata{ string username;}
class Users{
int age;
CAdata[] info;
this(){
setNull();
}
void setNull(){
age = 0;
info ~= new CAdata();
}
}
class CaStore{
Users[] ccuser;
this(){
ccuser ~= new Users();
}
}
void main()
{
Users user1 = new Users();
user1.age = 24;
user1.info[0].username = "bob";
Users user2 = new Users();
user2.age = 24;
user2.info[0].username = "alice";
CaStore db = new CaStore();
db.ccuser[0] = user1;
db.ccuser[1] = user2;
}
或C ++ 14:
#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;
};
答案 1 :(得分:0)
为了使可变参数模板有趣,我提出了一些解决方案。
它们两者都基于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, "!" );
}