【发布时间】:2020-09-11 19:33:51
【问题描述】:
我有以下代码...
#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 实现在 https://stackoverflow.com/a/16252940/11722. 中找到
【问题讨论】:
-
如果你只是想为各种枚举实现
operator<<,为什么还要为模板而烦恼呢?只需为每个类型依次实现operator<<,并将其放在与该类型相同的命名空间中,ADL 将完成剩下的工作。 -
会有更多的功能,而不仅仅是 operator
-
如果我确实需要它,我倾向于定义所有相关函数的特征类型,以及
typedef std::integral_constant<bool, true> traits_defined,我使用该 typedef 作为 enable_if 的一部分(非专用版本的 typedef 设置为 false)。但同样,如果您只是禁用函数,我发现在大多数情况下使用参数的重载函数是“更清洁”的解决方案。
标签: c++ templates c++14 template-meta-programming sfinae