如何分组不同的静态类?
How to group different static classes?
我有一个具有不同专业化的静态模板 class,如下所示:
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;
};
现在我想以某种方式将这些信息分组到一个新的 class
template<typename MyClass1, typename MyClasses... >
class MyGroupClass{
//do something...}
我可以在其中提供不同的 classes 作为可变模板参数,然后我可以访问不同的静态方法。
例如,我想用 MyGroupClass[n]::myarraysize
来访问与第 n 个 MyClass
.
相关的 myarraysize
我想我可以创建一个元组(所以有 std::get<n>()
),但我不太清楚如何做到这一点,因为我没有这种单一静态 classes 的构造函数.毕竟,classes 是静态的。
是否可以达到我想要的效果?如果是这样,你能赐教吗?谢谢。
I would like to to something as MyGroupClass[n]:: myarraysize to access myarraysize related to n-th MyClass. I imagine I could create a tuple (so having 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()
的尾随 return 类型并简单地编写
template <std::size_t N>
auto get () const
{ return std::get<N>(tpl); }
观察到 MyGroupStruct::get()
接收索引 (N
) 作为模板参数。所以它需要一个编译时已知值。这是必要的,因为从模板方法中编辑的类型 return 与索引不同,因此 必须 是已知的编译时间。
(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()
的 return 值始终相同,因此它可以接收 运行 时间索引作为(非模板)参数。
以下是不同类型(基于元组)案例的完整编译示例
#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 询问
how to change the code if I want to access also myarray and not only myarraysize?
C 风格的数组稍微复杂一些,因为你不能用 C 风格的数组初始化 C 风格数组的元组。
我建议您对 C 样式数组使用 引用 的元组。
所以,给定一些只有 myarray
的 MyClass
(为什么要在可以推断的情况下添加大小?)
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]; }
};
what does this stand for "const -> decltype(std::get(tpl))"?
const
与 decltype()
.
无关
const
,在方法参数列表后,说该方法也可以被常量对象使用,因为不改变成员变量。
关于 decltype()
查找 "trailing return type" 了解更多信息。
简而言之,对于 C++11,想法是在
auto foo () -> decltype(something)
{ return something; }
auto
说 "look after -> for the return type" 而 decltype(something)
是 "the type of something
"
你也可以这样写
decltype(something) foo ()
{ return something; }
如果 something
在函数参数列表之前已知,但是 auto
/-> decltype(something)
形式在 something
包含模板参数时变得有用
举例
template <typename T1, typename T2>
auto sum (T1 const & t1, T2 const & t2) -> decltype(t1+t2)
{ return t1+t2; }
从 C++14 开始,"trailing return type" 较少使用,因为您可以简单地编写
template <typename T1, typename T2>
auto sum (T1 const & t1, T2 const & t2)
{ return t1+t2; }
因为 auto
对编译器说 "deduce the return type from the return
expression"(所以在这种情况下来自 t1+t2
。
这避免了很多冗余。
And can we use "auto" also in C++11?
auto
为 return 类型?没有尾随 return 类型?
遗憾的是,仅从 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, "!" );
}
我有一个具有不同专业化的静态模板 class,如下所示:
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;
};
现在我想以某种方式将这些信息分组到一个新的 class
template<typename MyClass1, typename MyClasses... >
class MyGroupClass{
//do something...}
我可以在其中提供不同的 classes 作为可变模板参数,然后我可以访问不同的静态方法。
例如,我想用 MyGroupClass[n]::myarraysize
来访问与第 n 个 MyClass
.
myarraysize
我想我可以创建一个元组(所以有 std::get<n>()
),但我不太清楚如何做到这一点,因为我没有这种单一静态 classes 的构造函数.毕竟,classes 是静态的。
是否可以达到我想要的效果?如果是这样,你能赐教吗?谢谢。
I would like to to something as MyGroupClass[n]:: myarraysize to access myarraysize related to n-th MyClass. I imagine I could create a tuple (so having 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()
的尾随 return 类型并简单地编写
template <std::size_t N>
auto get () const
{ return std::get<N>(tpl); }
观察到 MyGroupStruct::get()
接收索引 (N
) 作为模板参数。所以它需要一个编译时已知值。这是必要的,因为从模板方法中编辑的类型 return 与索引不同,因此 必须 是已知的编译时间。
(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()
的 return 值始终相同,因此它可以接收 运行 时间索引作为(非模板)参数。
以下是不同类型(基于元组)案例的完整编译示例
#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 询问
how to change the code if I want to access also myarray and not only myarraysize?
C 风格的数组稍微复杂一些,因为你不能用 C 风格的数组初始化 C 风格数组的元组。
我建议您对 C 样式数组使用 引用 的元组。
所以,给定一些只有 myarray
的 MyClass
(为什么要在可以推断的情况下添加大小?)
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]; }
};
what does this stand for "const -> decltype(std::get(tpl))"?
const
与 decltype()
.
const
,在方法参数列表后,说该方法也可以被常量对象使用,因为不改变成员变量。
关于 decltype()
查找 "trailing return type" 了解更多信息。
简而言之,对于 C++11,想法是在
auto foo () -> decltype(something)
{ return something; }
auto
说 "look after -> for the return type" 而 decltype(something)
是 "the type of something
"
你也可以这样写
decltype(something) foo ()
{ return something; }
如果 something
在函数参数列表之前已知,但是 auto
/-> decltype(something)
形式在 something
包含模板参数时变得有用
举例
template <typename T1, typename T2>
auto sum (T1 const & t1, T2 const & t2) -> decltype(t1+t2)
{ return t1+t2; }
从 C++14 开始,"trailing return type" 较少使用,因为您可以简单地编写
template <typename T1, typename T2>
auto sum (T1 const & t1, T2 const & t2)
{ return t1+t2; }
因为 auto
对编译器说 "deduce the return type from the return
expression"(所以在这种情况下来自 t1+t2
。
这避免了很多冗余。
And can we use "auto" also in C++11?
auto
为 return 类型?没有尾随 return 类型?
遗憾的是,仅从 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, "!" );
}