使用 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>...>;