C++ 模板是否可以(仅)匹配一种类型或一种其他类型的列表?
Can a C++ template match (only) a list of one type, or a single other type?
我想编写模板来构造比方说输入端口。这可以通过单个输入输出端口或输入引脚列表来完成。我更喜欢那些模板具有相同的名称。我对输入输出端口和输入引脚都有概念。我会写
template< typename... arguments >
struct port_in ....
template< pin_in T >
struct port_in<> ....
但现在列表版本将接受任何类型。我可以在实现中检查它,但这会降低用户在传递不适合的类型时收到的错误消息。我能否以某种方式将列表限制为一种类型,但允许另一种类型的单个模板参数?
如果列表版本需要数字,你可以做到:
template<uint16_t ... Ports>
struct port_in ....
如果它可以接受非整数并且你想要一个实际的类型列表(并不是所有的参数都需要是同一类型),我不确定是否有一种干净的方法来做到这一点。如果您可以要求所有类型都相同,我想您可以这样做:
template<typename T, std::enable_if_t<T> * = nullptr>
struct port_in_base{};
template<typename T, T ... ports>
struct port_in : port_in_base<T> ....
如果要确保用户始终得到合理的错误消息,则需要对基本模板进行约束。假设您现有的概念被命名为 InputPin
和 InputOutputPort
,您可以限制基本模板接受输入引脚序列或单个 input/output 端口,如下所示:
template<class... Ts>
concept bool AllInputPins = (InputPin<Ts> && ...);
template<class... Ts>
concept bool OneInputOutputPort = sizeof...(Ts) == 1 && (InputOutputPort<Ts> && ...);
template <class... Args>
requires AllInputPins<Args...> || OneInputOutputPort<Args...>
struct port_in {
// ...
};
我想编写模板来构造比方说输入端口。这可以通过单个输入输出端口或输入引脚列表来完成。我更喜欢那些模板具有相同的名称。我对输入输出端口和输入引脚都有概念。我会写
template< typename... arguments >
struct port_in ....
template< pin_in T >
struct port_in<> ....
但现在列表版本将接受任何类型。我可以在实现中检查它,但这会降低用户在传递不适合的类型时收到的错误消息。我能否以某种方式将列表限制为一种类型,但允许另一种类型的单个模板参数?
如果列表版本需要数字,你可以做到:
template<uint16_t ... Ports>
struct port_in ....
如果它可以接受非整数并且你想要一个实际的类型列表(并不是所有的参数都需要是同一类型),我不确定是否有一种干净的方法来做到这一点。如果您可以要求所有类型都相同,我想您可以这样做:
template<typename T, std::enable_if_t<T> * = nullptr>
struct port_in_base{};
template<typename T, T ... ports>
struct port_in : port_in_base<T> ....
如果要确保用户始终得到合理的错误消息,则需要对基本模板进行约束。假设您现有的概念被命名为 InputPin
和 InputOutputPort
,您可以限制基本模板接受输入引脚序列或单个 input/output 端口,如下所示:
template<class... Ts>
concept bool AllInputPins = (InputPin<Ts> && ...);
template<class... Ts>
concept bool OneInputOutputPort = sizeof...(Ts) == 1 && (InputOutputPort<Ts> && ...);
template <class... Args>
requires AllInputPins<Args...> || OneInputOutputPort<Args...>
struct port_in {
// ...
};