C++ C++;多参数上的部分类模板专门化

C++ C++;多参数上的部分类模板专门化,c++,templates,c++17,partial-specialization,C++,Templates,C++17,Partial Specialization,我试图从本质上定义一个表示硬件外围设备的模板类,它有一些可重新映射的管脚。由于映射是在编译时(实际上是硬件原理图绘制时)定义的,所以我想通过模板参数引入这些定义。然而,由于每个管脚都可以独立于其他管脚进行映射,因此可能的类型集基本上是各个映射的笛卡尔积,我不确定这是否可以实现。我现在得到的是: enum class SPI1_NSS { PA4, PA15 }; enum class SPI1_SCK { PA5,

我试图从本质上定义一个表示硬件外围设备的模板类,它有一些可重新映射的管脚。由于映射是在编译时(实际上是硬件原理图绘制时)定义的,所以我想通过模板参数引入这些定义。然而,由于每个管脚都可以独立于其他管脚进行映射,因此可能的类型集基本上是各个映射的笛卡尔积,我不确定这是否可以实现。我现在得到的是:

     enum class SPI1_NSS {
        PA4,
        PA15
     };

     enum class SPI1_SCK {
        PA5,
        PB3
     };

     template<SPI1_NSS nss_enum, SPI1_SCK sck_enum>
     struct SPI_1 {
        //...other stuff

        struct nss;
        struct sck;

     };

     template<SPI1_SCK sck>
     struct SPI_1<SPI1_NSS::PA4, sck>::nss {
        using pin = GPIOs::A::pin<4>;
     };

     template<SPI1_SCK sck>
     struct SPI_1<SPI1_NSS::PA15, sck>::nss {
        using pin = GPIOs::A::pin<15>;
     };

     template<SPI1_NSS nss>
     struct SPI_1<nss, SPI1_SCK::PA5>::sck {
        using pin = GPIOs::A::pin<5>;
     };

     template<SPI1_NSS nss>
     struct SPI_1<nss, SPI1_SCK::PB3>::sck {
        using pin = GPIOs::B::pin<3>;
     };
enum类SPI1\u NSS{
PA4,
PA15
};
枚举类SPI1\U SCK{
PA5,
PB3
};
模板
结构SPI_1{
//…其他东西
结构nss;
结构sck;
};
模板
结构SPI_1::nss{
使用pin=GPIOs::A::pin;
};
模板
结构SPI_1::nss{
使用pin=GPIOs::A::pin;
};
模板
结构SPI_1::sck{
使用pin=GPIOs::A::pin;
};
模板
结构SPI_1::sck{
使用pin=GPIOs::B::pin;
};
此操作失败,出现
错误:“class HAL::SPI_1::nss”声明中的类名无效
以及其他类似错误。如果我删除两个模板参数中的一个,它就会工作

我期望得到的是,例如

    using spi = SPI_1<SPI1_NSS::PA4, SPI1_SCK::PB3>;
使用spi=spi_1;
类型
spi::nss::pin
将是
GPIOs::A::pin
spi::sck::pin
将是
GPIOs::B::pin
。这种“笛卡尔专门化”是否可能


我确实意识到我可以直接在GPIO类型上创建模板,这有点过度设计了。然而,我从中得到的好处是,枚举只提供并保证管脚的有效选择,因此它提供了更清晰的接口。

如果您想专门化正交性,我会使用不同的元函数,这些元函数不嵌套在
SPI_1

namespace detail {
  template<SPI1_NSS>
  stuct nss;

  template<>
  struct nss<PA4> {
    using pin = GPIOs::A::pin<4>;
  };

  template<>
  struct nss<PA15> {
    using pin = GPIOs::A::pin<15>;
  };

  // Same for sck
}

template<SPI1_NSS nss_enum, SPI1_SCK sck_enum>
struct SPI_1 {
   //...other stuff

   using nss = detail::nss<nss_enum>;
   using sck = detail::sck<sck_enum>;
};
名称空间详细信息{
模板
stuct-nss;
模板
结构nss{
使用pin=GPIOs::A::pin;
};
模板
结构nss{
使用pin=GPIOs::A::pin;
};
//同样适用于sck
}
模板
结构SPI_1{
//…其他东西
使用nss=详细信息::nss;
使用sck=detail::sck;
};

当然,由于我能够在单参数情况下使用嵌套版本,所以我不知何故被困在了嵌套版本上,而且可以说它更“优雅”。我会按惯例等待24小时,然后接受你的答复。