只接受枚举类型的函数
Function that only accepts enumeration types
伙计,我受不了这个该死的模板没有mo'
假设我有这个功能...
void sort(vector<int>& vec)
{
// stuff
}
我怎样才能使该函数接受所有枚举类型的向量而不重载它该死的 10 次?
我对模板知之甚少,但正在考虑做这样的事情......(这给了我错误:不允许使用类型名称)
template<typename T, std::enable_if_t<std::is_enum<T>>>
void sort(vector<T>& vec)
{
// stuff
}
你们非常亲密:
#include <vector>
template<typename T, typename =std::enable_if_t<std::is_enum<T>::value>>
void sort(std::vector<T>& vec)
{
// stuff
}
enum x {};
void foo()
{
std::vector<x> X;
std::vector<int> Y;
sort(X); // Works
sort(Y); // ERROR
}
使用 C++17,您可以节省一些输入:
template<typename T, typename =std::enable_if_t<std::is_enum_v<T>>>
void sort(std::vector<T>& vec)
{
// stuff
}
首先:您必须使用 std::is_enum<T>
的值,而不是 class 本身。
其次:计算 std::enable_if_t<std::is_enum<T>::value>
是 void
而 T
是 enum
.
因此,当 T
是一个 enum
时,您的函数将变为
// ..................VVVV void what ?
template<typename T, void>
void sort(vector<T>& vec)
{
// stuff
}
可能的解决方案是在左侧添加一个 typename
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
void sort(vector<T>& vec)
{
// stuff
}
可行,但有一个缺点:如果您必须 enable/disable 只有 sort()
的一个版本,一切顺利。但是如果你想要两个不同的 sort()
函数(比如一个用于枚举,一个用于非枚举)
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
void sort(vector<T>& vec)
{
// stuff
}
template<typename T, typename = std::enable_if_t<not std::is_enum<T>::value>>
void sort(vector<T>& vec)
{
// stuff
}
这是行不通的,因为你不能有两个具有相同签名的函数(默认模板 type/value 不会更改签名)和 SFINAE 失败,仅删除默认类型第二个参数,不禁用该函数,只是不允许它在不表达第二个模板参数的情况下匹配。
这个问题的解决方法:让SFINAE在等号左边工作如下
template<typename T,
std::enable_if_t<std::is_enum<T>::value, std::nullptr_t> = nullptr>
void sort(vector<T>& vec)
{
// stuff
}
template<typename T,
std::enable_if_t<not std::is_enum<T>::value, std::nullptr_t> = nullptr>
void sort(vector<T>& vec)
{
// stuff
}
这样 SFINAE enable/disable 函数,所以两个替代函数可以工作而不会相互干扰。
另一种方法(兼容两个替代函数)是使用 SFINAE enable/disable 返回类型,所以
template<typename T>
std::enable_if_t<std::is_enum<T>::value> sort(vector<T>& vec)
{
// stuff
}
template<typename T>
std::enable_if_t<not std::is_enum<T>::value> sort(vector<T>& vec)
{
// stuff
}
一些额外的未请求建议:
不会在标准库中将您的 classes 和函数命名为 classes/functions;因此,请为您的 sort()
取一个不同的名称,以避免与标准 std::sort()
发生冲突
避免using namespace std;
,或者真的更可能发生名称冲突(调用sort()
,被称为你的sort()
或std::sort()
?)
如果您使用全新的 C++(如果可能,我会推荐)。有一个使用概念 (c++20) 的工作示例。刚刚在 gcc 10
测试
#include <type_traits>
#include <vector>
#include <concepts>
template<typename T> requires std::is_enum<T>::value
void sort(std::vector<T> & vec)
{
// stuff
}
int main()
{
enum Mew
{
neat,
ugly
};
std::vector<Mew> v;
sort(v); //works
std::vector<int> v_int;
sort(v_int); //error here
return 0;
}
伙计,我受不了这个该死的模板没有mo'
假设我有这个功能...
void sort(vector<int>& vec)
{
// stuff
}
我怎样才能使该函数接受所有枚举类型的向量而不重载它该死的 10 次?
我对模板知之甚少,但正在考虑做这样的事情......(这给了我错误:不允许使用类型名称)
template<typename T, std::enable_if_t<std::is_enum<T>>>
void sort(vector<T>& vec)
{
// stuff
}
你们非常亲密:
#include <vector>
template<typename T, typename =std::enable_if_t<std::is_enum<T>::value>>
void sort(std::vector<T>& vec)
{
// stuff
}
enum x {};
void foo()
{
std::vector<x> X;
std::vector<int> Y;
sort(X); // Works
sort(Y); // ERROR
}
使用 C++17,您可以节省一些输入:
template<typename T, typename =std::enable_if_t<std::is_enum_v<T>>>
void sort(std::vector<T>& vec)
{
// stuff
}
首先:您必须使用 std::is_enum<T>
的值,而不是 class 本身。
其次:计算 std::enable_if_t<std::is_enum<T>::value>
是 void
而 T
是 enum
.
因此,当 T
是一个 enum
时,您的函数将变为
// ..................VVVV void what ?
template<typename T, void>
void sort(vector<T>& vec)
{
// stuff
}
可能的解决方案是在左侧添加一个 typename
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
void sort(vector<T>& vec)
{
// stuff
}
可行,但有一个缺点:如果您必须 enable/disable 只有 sort()
的一个版本,一切顺利。但是如果你想要两个不同的 sort()
函数(比如一个用于枚举,一个用于非枚举)
template<typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
void sort(vector<T>& vec)
{
// stuff
}
template<typename T, typename = std::enable_if_t<not std::is_enum<T>::value>>
void sort(vector<T>& vec)
{
// stuff
}
这是行不通的,因为你不能有两个具有相同签名的函数(默认模板 type/value 不会更改签名)和 SFINAE 失败,仅删除默认类型第二个参数,不禁用该函数,只是不允许它在不表达第二个模板参数的情况下匹配。
这个问题的解决方法:让SFINAE在等号左边工作如下
template<typename T,
std::enable_if_t<std::is_enum<T>::value, std::nullptr_t> = nullptr>
void sort(vector<T>& vec)
{
// stuff
}
template<typename T,
std::enable_if_t<not std::is_enum<T>::value, std::nullptr_t> = nullptr>
void sort(vector<T>& vec)
{
// stuff
}
这样 SFINAE enable/disable 函数,所以两个替代函数可以工作而不会相互干扰。
另一种方法(兼容两个替代函数)是使用 SFINAE enable/disable 返回类型,所以
template<typename T>
std::enable_if_t<std::is_enum<T>::value> sort(vector<T>& vec)
{
// stuff
}
template<typename T>
std::enable_if_t<not std::is_enum<T>::value> sort(vector<T>& vec)
{
// stuff
}
一些额外的未请求建议:
不会在标准库中将您的 classes 和函数命名为 classes/functions;因此,请为您的
发生冲突sort()
取一个不同的名称,以避免与标准std::sort()
避免
using namespace std;
,或者真的更可能发生名称冲突(调用sort()
,被称为你的sort()
或std::sort()
?)
如果您使用全新的 C++(如果可能,我会推荐)。有一个使用概念 (c++20) 的工作示例。刚刚在 gcc 10
测试#include <type_traits>
#include <vector>
#include <concepts>
template<typename T> requires std::is_enum<T>::value
void sort(std::vector<T> & vec)
{
// stuff
}
int main()
{
enum Mew
{
neat,
ugly
};
std::vector<Mew> v;
sort(v); //works
std::vector<int> v_int;
sort(v_int); //error here
return 0;
}