如何对不同的静态类进行分组?
How to group different static classes?
我有一个具有不同专业的模板化静态类,如下所示:
template<typename Parameter >
class MyClass
{};
template<>
class MyClass<Parameter1>
{
public:
static constexpr Integer myarray[]={0};
static constexpr Integer myarraysize=1;
};
template<>
class MyClass<Parameter2>
{
public:
static constexpr Integer myarray[]={0,1};
static constexpr Integer myarraysize=2;
};
现在我想以某种方式将这些信息分组到一个新类中
template<typename MyClass1, typename MyClasses... >
class MyGroupClass{
//do something...}
我可以在其中为不同的类提供可变参数模板参数,然后可以访问不同的静态方法。
例如,我想MyGroupClass[n]::myarraysize
访问与第 n 个MyClass
相关的myarraysize
。我想我可以创建一个元组(所以有std::get<n>()
),但我不太清楚如何做到这一点,因为我没有这种单一静态类的构造函数。毕竟,类是静态的。
有可能实现我想要的吗?如果是这样,你能开导我吗?谢谢。
我想像 MyGroupClass[n]:: myarraysize 来访问与第 n 个 MyClass 相关的 myarraysize。我想我可以创建一个元组(所以有 std::get()),
在我看来,你必须区分两种情况。
(1)当不同类中的myarraysize
具有不同的类型时,您可以创建不同大小的std::tuple
,std::get()
提取值。
通过示例
template <typename ... Ts>
struct MyGroupStruct
{
const std::tuple<decltype(Ts::myarraysize)...> tpl { Ts::myarraysize... };
template <std::size_t N>
auto get () const -> decltype(std::get<N>(tpl))
{ return std::get<N>(tpl); }
};
从 C++14 开始,您可以避免get()
的尾随返回类型并简单地写入
template <std::size_t N>
auto get () const
{ return std::get<N>(tpl); }
观察到MyGroupStruct::get()
接收索引 (N
) 作为模板参数。所以它需要一个编译时已知值。这是必需的,因为从模板方法返回的类型因索引而异,因此必须在编译时知道。
(2)当不同类中的所有myarraysize
都属于同一类型时,您也可以创建该类型的std::array
;
template <typename ... Ts>
struct MyGroupStruct
{
using myType = typename std::tuple_element<0u,
std::tuple<decltype(Ts::myarraysize)...>>::type;
const std::array<myType, sizeof...(Ts)> arr {{ Ts::myarraysize... }};
myType & get (std::size_t n)
{ return arr[n]; }
};
请注意,在这种情况下,get()
的返回值永远相同,因此它可以接收运行时索引作为(而不是模板)参数。
以下是不同类型(基于元组)情况的完整编译示例
#include <tuple>
#include <string>
#include <iostream>
struct Par1 {};
struct Par2 {};
struct Par3 {};
struct Par4 {};
template <typename>
struct MyStruct;
template <>
struct MyStruct<Par1>
{ static constexpr int myarraysize {1}; };
constexpr int MyStruct<Par1>::myarraysize;
template <>
struct MyStruct<Par2>
{ static constexpr long myarraysize {2l}; };
constexpr long MyStruct<Par2>::myarraysize;
template <>
struct MyStruct<Par3>
{ static constexpr long long myarraysize {3ll}; };
constexpr long long MyStruct<Par3>::myarraysize;
template <>
struct MyStruct<Par4>
{ static const std::string myarraysize; };
const std::string MyStruct<Par4>::myarraysize {"four"};
template <typename ... Ts>
struct MyGroupStruct
{
const std::tuple<decltype(Ts::myarraysize)...> tpl { Ts::myarraysize... };
template <std::size_t N>
auto get () const -> decltype(std::get<N>(tpl))
{ return std::get<N>(tpl); }
};
int main ()
{
MyGroupStruct<MyStruct<Par1>, MyStruct<Par2>,
MyStruct<Par3>, MyStruct<Par4>> mgs;
std::cout << mgs.get<0>() << std::endl;
std::cout << mgs.get<1>() << std::endl;
std::cout << mgs.get<2>() << std::endl;
std::cout << mgs.get<3>() << std::endl;
static_assert( std::is_same<int const &,
decltype(mgs.get<0>())>::value, "!" );
static_assert( std::is_same<long const &,
decltype(mgs.get<1>())>::value, "!" );
static_assert( std::is_same<long long const &,
decltype(mgs.get<2>())>::value, "!" );
static_assert( std::is_same<std::string const &,
decltype(mgs.get<3>())>::value, "!" );
}
现在是相等类型(基于数组)情况的完整编译示例
#include <tuple>
#include <array>
#include <string>
#include <iostream>
struct Par1 {};
struct Par2 {};
struct Par3 {};
struct Par4 {};
template <typename>
struct MyStruct;
template <>
struct MyStruct<Par1>
{ static constexpr int myarraysize {1}; };
constexpr int MyStruct<Par1>::myarraysize;
template <>
struct MyStruct<Par2>
{ static constexpr int myarraysize {2}; };
constexpr int MyStruct<Par2>::myarraysize;
template <>
struct MyStruct<Par3>
{ static constexpr int myarraysize {3}; };
constexpr int MyStruct<Par3>::myarraysize;
template <>
struct MyStruct<Par4>
{ static const int myarraysize {4}; };
const int MyStruct<Par4>::myarraysize;
template <typename ... Ts>
struct MyGroupStruct
{
using myType = typename std::tuple_element<0u,
std::tuple<decltype(Ts::myarraysize)...>>::type;
const std::array<myType, sizeof...(Ts)> arr {{ Ts::myarraysize... }};
myType & get (std::size_t n)
{ return arr[n]; }
};
int main ()
{
MyGroupStruct<MyStruct<Par1>, MyStruct<Par2>,
MyStruct<Par3>, MyStruct<Par4>> mgs;
std::cout << mgs.get(0) << std::endl;
std::cout << mgs.get(1) << std::endl;
std::cout << mgs.get(2) << std::endl;
std::cout << mgs.get(3) << std::endl;
static_assert( std::is_same<int const &,
decltype(mgs.get(0))>::value, "!" );
}
--编辑--
OP问
如果我还想访问 myarray,而不仅仅是 myarraysize,如何更改代码?
使用 C 样式数组稍微复杂一些,因为您无法使用 C 样式数组初始化 C 样式数组的元组。
我建议你使用一个对 C 样式数组的引用元组。
因此,给定一些只有myarray
的MyClass
es(当您可以推断出大小时,为什么要添加大小?
template <typename>
struct MyStruct;
template <>
struct MyStruct<Par1>
{ static constexpr int myarray[] {0}; };
constexpr int MyStruct<Par1>::myarray[];
// other MyStruct specializations ...
您可以添加引用元组(元组,而不是std::array
元组,因为int[1]
、int[2]
、int[3]
和int[4]
都是不同的类型)和大小std::array<std::size_t, sizeof...(Ts)>
。
我的意思是。。。你可以写如下内容
template <typename ... Ts>
struct MyGroupStruct
{
std::tuple<decltype(Ts::myarray) & ...> const tpl { Ts::myarray... };
std::array<std::size_t, sizeof...(Ts)> const arr
{{ sizeof(Ts::myarray)/sizeof(Ts::myarray[0])... }};
template <std::size_t N>
auto getArr () const -> decltype(std::get<N>(tpl))
{ return std::get<N>(tpl); }
std::size_t getSize (std::size_t n) const
{ return arr[n]; }
};
这代表什么"const -> decltype(std::get(tpl))"?
const
与decltype()
无关。
const
,在方法参数列表之后,说该方法也可以由常量对象使用,因为不会更改成员变量。
关于decltype()
查找"尾随返回类型"以获取更多信息。
简而言之,对于 C++11,这个想法是
auto foo () -> decltype(something)
{ return something; }
auto
说"照顾->返回类型",decltype(something)
是"something
的类型">
你也可以写
decltype(something) foo ()
{ return something; }
如果在函数参数列表之前已知something
,但是当something
包含模板参数时,auto
/-> decltype(something)
形式变得有用
通过示例
template <typename T1, typename T2>
auto sum (T1 const & t1, T2 const & t2) -> decltype(t1+t2)
{ return t1+t2; }
从 C++14 开始,"尾随返回类型"较少使用,因为您可以简单地编写
template <typename T1, typename T2>
auto sum (T1 const & t1, T2 const & t2)
{ return t1+t2; }
因为auto
编译器说"从return
表达式中推断返回类型"(在这种情况下从t1+t2
推断。这避免了很多冗余。
我们可以在 C++11 中也使用"自动"吗?
auto
作为返回类型?没有尾随返回类型?
不幸的是,仅从 C++14 开始可用。
遵循另一个具有myarray
和推导大小的完整示例。
#include <tuple>
#include <array>
#include <string>
#include <iostream>
struct Par1 {};
struct Par2 {};
struct Par3 {};
struct Par4 {};
template <typename>
struct MyStruct;
template <>
struct MyStruct<Par1>
{ static constexpr int myarray[] {0}; };
constexpr int MyStruct<Par1>::myarray[];
template <>
struct MyStruct<Par2>
{ static constexpr int myarray[] {0, 1}; };
constexpr int MyStruct<Par2>::myarray[];
template <>
struct MyStruct<Par3>
{ static constexpr int myarray[] {0, 1, 2}; };
constexpr int MyStruct<Par3>::myarray[];
template <>
struct MyStruct<Par4>
{ static constexpr int myarray[] {0, 1, 2, 3}; };
constexpr int MyStruct<Par4>::myarray[];
template <typename ... Ts>
struct MyGroupStruct
{
std::tuple<decltype(Ts::myarray) & ...> const tpl { Ts::myarray... };
std::array<std::size_t, sizeof...(Ts)> const arr
{{ sizeof(Ts::myarray)/sizeof(Ts::myarray[0])... }};
template <std::size_t N>
auto getArr () const -> decltype(std::get<N>(tpl))
{ return std::get<N>(tpl); }
std::size_t getSize (std::size_t n) const
{ return arr[n]; }
};
int main ()
{
MyGroupStruct<MyStruct<Par1>, MyStruct<Par2>,
MyStruct<Par3>, MyStruct<Par4>> mgs;
std::cout << mgs.getSize(0) << std::endl;
std::cout << mgs.getSize(1) << std::endl;
std::cout << mgs.getSize(2) << std::endl;
std::cout << mgs.getSize(3) << std::endl;
static_assert( std::is_same<std::size_t,
decltype(mgs.getSize(0))>::value, "!" );
std::cout << mgs.getArr<0>()[0] << std::endl;
std::cout << mgs.getArr<1>()[1] << std::endl;
std::cout << mgs.getArr<2>()[2] << std::endl;
std::cout << mgs.getArr<3>()[3] << std::endl;
static_assert( std::is_same<int const (&)[1],
decltype(mgs.getArr<0>())>::value, "!" );
static_assert( std::is_same<int const (&)[2],
decltype(mgs.getArr<1>())>::value, "!" );
static_assert( std::is_same<int const (&)[3],
decltype(mgs.getArr<2>())>::value, "!" );
static_assert( std::is_same<int const (&)[4],
decltype(mgs.getArr<3>())>::value, "!" );
}
- 在C++中使用非静态类函数的函数
- (为什么)我们可以在初始化中将非静态类成员分配给静态变量吗?
- 在C++中,为什么使用静态类函数而不是常规函数?
- 静态类属性,C++中的多个构造函数
- 如何从静态类函数初始化静态类对象
- 在 c++ 中使用字符串变量选择静态类结构,而不带对象
- 是否通过单元化指针UB访问静态类成员
- 如何在 c++ 中初始化静态类对象?
- 为静态类创建指向对象的指针是否合法?
- thread_local静态类在程序退出时在无效地址处销毁
- 从静态成员函数访问私有非静态类变量 - C++
- 在子类中填充静态类成员
- 静态类变量的多重定义
- 作为成员的静态类模板实例会导致未解析的外部符号错误
- uninit_member:非静态类成员字段 m_cJobState.bstatus 未在此构造函数中初始化,也不在其调
- uninit_member:非静态类成员m_wszParams未在此构造函数中初始化,也不在它C++中调用的任何函数中初
- 说明通过指针访问非静态类成员函数
- 静态类数据成员的线程安全
- 静态类成员的使用
- 静态类成员不是与 this 指针没有关联吗?