使用 std::index_sequence 使用许多模板参数配置的递归聚合类型
Recursive aggregate type configured using many template parameters using std::index_sequence
有一个class模板:
template<std::size_t ID, std::size_t T1, std::size_t T2, std::size_t T3>
class Feature { /* Implementation goes here */ };
Feature<...>
的所有实例都在'collected'这里:
template<typename FEATURE, typename... OTHERS>
class Features<FEATURE, OTHERS...> : public Features<OTHERS...> {
public:
/* Operations defined here */
private:
FEATURE m_feature;
};
所有特征创建如下:
using FeatureConfig = Features<Feature<0, 1, 2, 3>, Feature<1, 4, 5, 6>>;
FeatureConfig m_features;
到目前为止一切顺利。我的任务是摆脱 1..3、4..6 等中的那些硬编码值。这样做的方法是生成包含所有功能配置的头文件。类似于:
template<std::size_t> struct Config;
template<>
struct Config<0> {
static constexpr std::size_t t1 { 1 };
static constexpr std::size_t t2 { 2 };
static constexpr std::size_t t3 { 3 };
};
template<>
struct Config<1> {
static constexpr std::size_t t1 { 4 };
static constexpr std::size_t t2 { 5 };
static constexpr std::size_t t3 { 6 };
};
然后我需要以某种方式更改 FeatureConfig
的类型定义以使用基于索引 (0, 1, ...) 的 FeatureConfig
的特化。我不成功的尝试是:
template<std::size_t... INDEX_SEQUENCE>
using FeatureConfig = Features<Feature<INDEX_SEQUENCE, Config<INDEX_SEQUENCE>::t1, Config<INDEX_SEQUENCE>::t2, Config<INDEX_SEQUENCE>::t3>...>;
FeatureConfig<std::make_index_sequence<2>> m_features;
看来我在某种程度上混合了类型和值...
非常感谢任何愿意帮助我修复上次列表中错误代码的人。
干杯马丁
如果我没理解错你想要什么...
我建议以下函数的声明(不需要定义,因为只在decltype()
中使用)
template <std::size_t ... Is>
auto getFeaturesType (std::index_sequence<Is...>)
-> Features<Feature<Is, Config<Is>::t1, Config<Is>::t2, Config<Is>::t3>...>;
现在你可以简单的定义FeatureConfig
如下
template <std::size_t N>
using FeatureConfig
= decltype(getFeaturesType(std::make_index_sequence<N>{}));
下面是一个完整的编译(简化)示例
#include <type_traits>
#include <utility>
template <std::size_t, std::size_t, std::size_t, std::size_t>
struct Feature { };
template <typename...>
struct Features
{ };
template <typename F, typename... Os>
struct Features<F, Os...> : public Features<Os...>
{ F m_feature; };
template <std::size_t N>
struct Config
{
static constexpr std::size_t t1 { N*3u };
static constexpr std::size_t t2 { 1u + N*3u };
static constexpr std::size_t t3 { 2u + N*3u };
};
template <std::size_t ... Is>
auto getFeaturesType (std::index_sequence<Is...>)
-> Features<Feature<Is, Config<Is>::t1, Config<Is>::t2, Config<Is>::t3>...>;
template <std::size_t N>
using FeatureConfig
= decltype(getFeaturesType(std::make_index_sequence<N>{}));
int main ()
{
using T1 = FeatureConfig<2u>;
using T2 = Features<Feature<0u, 0u, 1u, 2u>, Feature<1u, 3u, 4u, 5u>>;
static_assert( std::is_same<T1, T2>::value, "!" );
}
如果我理解正确,你如何使用 Config
(如果 t1
永远是 N*3u
,如果 t2
永远是 1u+N*3u
,如果 t3
永远是 2u+N*3u
),你完全可以避免 Config
而写 getFeaturesType
如下
template <std::size_t ... Is>
auto getFeaturesType (std::index_sequence<Is...>)
-> Features<Feature<Is, Is*3u, Is*3u+1u, Is*3u+2u>...>;
有一个class模板:
template<std::size_t ID, std::size_t T1, std::size_t T2, std::size_t T3>
class Feature { /* Implementation goes here */ };
Feature<...>
的所有实例都在'collected'这里:
template<typename FEATURE, typename... OTHERS>
class Features<FEATURE, OTHERS...> : public Features<OTHERS...> {
public:
/* Operations defined here */
private:
FEATURE m_feature;
};
所有特征创建如下:
using FeatureConfig = Features<Feature<0, 1, 2, 3>, Feature<1, 4, 5, 6>>;
FeatureConfig m_features;
到目前为止一切顺利。我的任务是摆脱 1..3、4..6 等中的那些硬编码值。这样做的方法是生成包含所有功能配置的头文件。类似于:
template<std::size_t> struct Config;
template<>
struct Config<0> {
static constexpr std::size_t t1 { 1 };
static constexpr std::size_t t2 { 2 };
static constexpr std::size_t t3 { 3 };
};
template<>
struct Config<1> {
static constexpr std::size_t t1 { 4 };
static constexpr std::size_t t2 { 5 };
static constexpr std::size_t t3 { 6 };
};
然后我需要以某种方式更改 FeatureConfig
的类型定义以使用基于索引 (0, 1, ...) 的 FeatureConfig
的特化。我不成功的尝试是:
template<std::size_t... INDEX_SEQUENCE>
using FeatureConfig = Features<Feature<INDEX_SEQUENCE, Config<INDEX_SEQUENCE>::t1, Config<INDEX_SEQUENCE>::t2, Config<INDEX_SEQUENCE>::t3>...>;
FeatureConfig<std::make_index_sequence<2>> m_features;
看来我在某种程度上混合了类型和值...
非常感谢任何愿意帮助我修复上次列表中错误代码的人。
干杯马丁
如果我没理解错你想要什么...
我建议以下函数的声明(不需要定义,因为只在decltype()
中使用)
template <std::size_t ... Is>
auto getFeaturesType (std::index_sequence<Is...>)
-> Features<Feature<Is, Config<Is>::t1, Config<Is>::t2, Config<Is>::t3>...>;
现在你可以简单的定义FeatureConfig
如下
template <std::size_t N>
using FeatureConfig
= decltype(getFeaturesType(std::make_index_sequence<N>{}));
下面是一个完整的编译(简化)示例
#include <type_traits>
#include <utility>
template <std::size_t, std::size_t, std::size_t, std::size_t>
struct Feature { };
template <typename...>
struct Features
{ };
template <typename F, typename... Os>
struct Features<F, Os...> : public Features<Os...>
{ F m_feature; };
template <std::size_t N>
struct Config
{
static constexpr std::size_t t1 { N*3u };
static constexpr std::size_t t2 { 1u + N*3u };
static constexpr std::size_t t3 { 2u + N*3u };
};
template <std::size_t ... Is>
auto getFeaturesType (std::index_sequence<Is...>)
-> Features<Feature<Is, Config<Is>::t1, Config<Is>::t2, Config<Is>::t3>...>;
template <std::size_t N>
using FeatureConfig
= decltype(getFeaturesType(std::make_index_sequence<N>{}));
int main ()
{
using T1 = FeatureConfig<2u>;
using T2 = Features<Feature<0u, 0u, 1u, 2u>, Feature<1u, 3u, 4u, 5u>>;
static_assert( std::is_same<T1, T2>::value, "!" );
}
如果我理解正确,你如何使用 Config
(如果 t1
永远是 N*3u
,如果 t2
永远是 1u+N*3u
,如果 t3
永远是 2u+N*3u
),你完全可以避免 Config
而写 getFeaturesType
如下
template <std::size_t ... Is>
auto getFeaturesType (std::index_sequence<Is...>)
-> Features<Feature<Is, Is*3u, Is*3u+1u, Is*3u+2u>...>;