要将模板参数包限制为特定类型,可以通过以下方式完成:
std::enable_if_t<std::conjunction_v<std::is_same<int32_t, Ts>...>>
send(bool condition, Ts...);
实际上,我会允许int32_t和std::string以及任何顺序。
如何表达?
我有一个使用变体的变通方法,但这对我来说不太好:
using allowed_types = std::variant<int32_t, std::string>;
template<typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_assignable<allowed_types, Ts>...>>
send(bool condition, Ts...);
这并不能编译:
std::enable_if_t<std::conjunction_v<std::is_same<int32_t, Ts> || std::is_same<std::string, Ts>...>> // <- does not compile!
send(bool condition, Ts...);
您在std::bool_constant
级别上正确地使用std::conjunction
作为&&
的替代品,但您应该以相同的方式将||
替换为std::disjunction
:
std::enable_if_t<std::conjunction_v<std::disjunction<std::is_same<int32_t, Ts>, std::is_same<std::string, Ts>>...>>
或者使用C++17,您可以在bool
值的级别上使用折叠表达式:
std::enable_if_t<((std::is_same_v<int32_t, Ts> || std::is_same_v<std::string, Ts>) && ...)>>
(折叠表达式语法需要外括号。(
当然,在C++20的帮助下,这可以做得更好:
template<typename T>
concept Int32OrString = std::same_as<T, int32_t> || std::same_as<T, std::string>;
void send(bool condition, Int32OrString auto...);
甚至
template<typename T, typename... Ts>
concept AnyOf = (std::same_as<T, Ts> || ...);
void send(bool condition, AnyOf<int32_t, std::string> auto...);