Can a C ++ template match (only) a list of one type or one other type?

I want to write templates for building let say input port. This can be done either from one I / O port or from the list of input contacts. I prefer those templates to have the same name. I have concepts for both an input / output port and input contacts. I can write

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

But now the version of the list will accept any type. I can verify this in the implementation, but this will lead to a deterioration of the error message that the user receives when he passes types that are not suitable. Is there any way to limit the list to one type, but to allow one template parameter of another type?

+5
source share
2 answers

If you want users to always receive a reasonable error message, you need to limit the base template. Assuming your existing concepts are called InputPin and InputOutputPort , you can restrict the base template to accept either a sequence of input pins or a single input / output port as follows:

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

If the list version should accept numbers, you can do this:

 template<uint16_t ... Ports> struct port_in .... 

I'm not sure there is a clean way to do this if it can take non-integer numbers and you need an actual list of types (these are not all arguments must be of the same type). If you can require all types to be the same, I think you could do something like:

 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> .... 
+1
source

Source: https://habr.com/ru/post/1274109/


All Articles