在多个模板上重复模板 enable_if 条件
Repeat template enable_if condition on multiple templates
我有以下代码...
#include <iostream>
#include <map>
template <typename T, typename...>
struct is_contained : std::false_type {};
template <typename T, typename Head, typename... Tail>
struct is_contained<T, Head, Tail...>
: std::integral_constant<bool, std::is_same<T, Head>::value ||
is_contained<T, Tail...>::value> {};
// Enum types
enum class Fruit { APPLE, BANANA };
// To string maps
std::map<Fruit, std::string> fruits = {{Fruit::APPLE, "apple"},
{Fruit::BANANA, "banana"}};
// Map string map to enum
template <typename T>
std::map<T, std::string> typeMap;
template <>
std::map<Fruit, std::string> typeMap<Fruit> = fruits;
// operator<< for mapped enums
template <typename T,
typename = std::enable_if_t<is_contained<T, Fruit>::value>>
std::ostream &operator<<(std::ostream &os, const T &t) {
os << typeMap<T>.at(t);
return os;
}
int main() {
Fruit f = Fruit::BANANA;
std::cout << f << std::endl;
return 0;
}
... 为各种枚举类型实现 operator<<
。现在具体行:
typename = std::enable_if_t<is_contained<T, Fruit>::value>>
确保我的流运算符实现仅用于我的特定类型,该类型将扩展为我所有用户枚举类型的列表。
我要解决的问题是如何在其他模板函数上重用该条件,而不必重复类型列表或使用宏。类似于:typename = TypeIsInMyList<T>
可能很简单,但我想不出什么。
在
中找到 is_contained
实现
如果我没理解错的话,你正在寻找一个简单的using
,比如
template <typename T>
using TypeIsInMyList
= std::enable_if_t<is_contained<T, Fruit, void, int, char>::value>;
您可以按如下方式使用
template <typename T,
typename = TypeIsInMyList<T>>
但是我建议修改如下
template <typename T>
using TypeIsInMyList
= std::enable_if_t<is_contained<T, Fruit, void, int, char>::value, int>;
并用在等号的左边
template <typename T,
TypeIsInMyList<T> = 0>
有点复杂但是...我不认为这有什么真正的区别,在你的情况下,但是当你在重载中有替代函数时,第二种解决方案是更好的方法。
这是 C++20 的处理方式:
template <typename T, typename ...P>
concept one_of = (std::same_as<T, P> || ...);
那你可以直接这样写:
template <one_of<Fruit, void, int, char> T>
std::ostream &operator<<(std::ostream &os, const T &t) {/*...*/}
或者再做一个概念:
template <typename T>
concept foo = one_of<T, Fruit, void, int, char>;
template <foo T>
std::ostream &operator<<(std::ostream &os, const T &t) {/*...*/}
我有以下代码...
#include <iostream>
#include <map>
template <typename T, typename...>
struct is_contained : std::false_type {};
template <typename T, typename Head, typename... Tail>
struct is_contained<T, Head, Tail...>
: std::integral_constant<bool, std::is_same<T, Head>::value ||
is_contained<T, Tail...>::value> {};
// Enum types
enum class Fruit { APPLE, BANANA };
// To string maps
std::map<Fruit, std::string> fruits = {{Fruit::APPLE, "apple"},
{Fruit::BANANA, "banana"}};
// Map string map to enum
template <typename T>
std::map<T, std::string> typeMap;
template <>
std::map<Fruit, std::string> typeMap<Fruit> = fruits;
// operator<< for mapped enums
template <typename T,
typename = std::enable_if_t<is_contained<T, Fruit>::value>>
std::ostream &operator<<(std::ostream &os, const T &t) {
os << typeMap<T>.at(t);
return os;
}
int main() {
Fruit f = Fruit::BANANA;
std::cout << f << std::endl;
return 0;
}
... 为各种枚举类型实现 operator<<
。现在具体行:
typename = std::enable_if_t<is_contained<T, Fruit>::value>>
确保我的流运算符实现仅用于我的特定类型,该类型将扩展为我所有用户枚举类型的列表。
我要解决的问题是如何在其他模板函数上重用该条件,而不必重复类型列表或使用宏。类似于:typename = TypeIsInMyList<T>
可能很简单,但我想不出什么。
在
中找到is_contained
实现
如果我没理解错的话,你正在寻找一个简单的using
,比如
template <typename T>
using TypeIsInMyList
= std::enable_if_t<is_contained<T, Fruit, void, int, char>::value>;
您可以按如下方式使用
template <typename T,
typename = TypeIsInMyList<T>>
但是我建议修改如下
template <typename T>
using TypeIsInMyList
= std::enable_if_t<is_contained<T, Fruit, void, int, char>::value, int>;
并用在等号的左边
template <typename T,
TypeIsInMyList<T> = 0>
有点复杂但是...我不认为这有什么真正的区别,在你的情况下,但是当你在重载中有替代函数时,第二种解决方案是更好的方法。
这是 C++20 的处理方式:
template <typename T, typename ...P>
concept one_of = (std::same_as<T, P> || ...);
那你可以直接这样写:
template <one_of<Fruit, void, int, char> T>
std::ostream &operator<<(std::ostream &os, const T &t) {/*...*/}
或者再做一个概念:
template <typename T>
concept foo = one_of<T, Fruit, void, int, char>;
template <foo T>
std::ostream &operator<<(std::ostream &os, const T &t) {/*...*/}