【问题标题】:Can a C++ template match (only) a list of one type, or a single other type?C++ 模板可以(仅)匹配一种类型的列表,还是一种其他类型的列表?
【发布时间】:2017-12-15 21:27:20
【问题描述】:

我想编写模板来构造一个输入端口。这可以通过单个输入输出端口或输入引脚列表来完成。我更喜欢这些模板具有相同的名称。我对输入输出端口和输入引脚都有概念。我会写

template< typename... arguments > 
struct port_in ....

template< pin_in T > 
struct port_in<> ....

但现在列表版本将接受任何类型。我可以在实现中检查这一点,但这会降低用户在传递不适合的类型时收到的错误消息。我可以以某种方式将列表限制为一种类型,但允许使用另一种类型的单个模板参数吗?

【问题讨论】:

    标签: c++ templates variadic-templates c++-concepts


    【解决方案1】:

    如果您想确保用户始终收到合理的错误消息,那么您需要约束基本模板。假设您现有的概念被命名为 InputPin 和 InputOutputPort,您可以将基本模板约束为接受一系列输入引脚或单个输入/输出端口,如下所示:

    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 {
      // ...
    };
    

    【讨论】:

    • 这看起来不错。我明天试试。我缺少的是概念接受列表的能力。
    • concept 是非标准的。
    • 是的,但我使用的是概念(问题标记为'c++concepts',并且我在问题文本中提到了概念。
    • PS 几年前,我尝试编写类似于我现在正在做的事情,而概念使这变得更容易(并且错误消息更好。不是很好,但好多了)。
    • 我成功地使用了这种风格。谢谢!
    【解决方案2】:

    如果列表版本应该采用数字,你可以做到:

    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> ....
    

    【讨论】:

    • I'm not sure there is a clean way to do this if it can take non-integers and you want an actual type list 标准方式是通过 std::integral_constant 或等效...
    • 模板参数都是类,不是整数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 2023-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多