C++ 专门针对枚举的函数
C++ specialise function on enum
是否可以在 enum
上特化模板函数?
我注意到 here 如果模板函数不是枚举,则可以将其禁用,但这是否可能同时仍允许其他类型?
我下面的示例显示了 int
、float
和 enum
的特化(它不会编译,因为它试图重载 enum
版本而不是特化它)。我觉得我遗漏了一些明显的东西。
请注意,我希望专注于 any 枚举,而不仅仅是命名枚举(示例中的 EAnEnum
)
#include <iostream>
enum class EAnEnum
{
Alpha,
Beta,
};
template<typename T>
void MyFunc();
template<>
void MyFunc<int>()
{
std::cout << "Int" << std::endl;
}
template<>
void MyFunc<float>()
{
std::cout << "Float" << std::endl;
}
// MyFunc<Enum>
template<typename T>
typename std::enable_if<std::is_enum<T>::value, void>::type MyFunc()
{
std::cout << "Enum" << std::endl;
}
int main()
{
MyFunc<EAnEnum>();
return 0;
}
您不能部分特化一个函数,但您可以使用 标签调度。
它遵循基于 OP 问题的最小工作示例:
#include <iostream>
#include<type_traits>
enum class EAnEnum
{
Alpha,
Beta,
};
template<typename>
struct tag {};
void MyFunc(tag<int>)
{
std::cout << "Int" << std::endl;
}
void MyFunc(tag<float>)
{
std::cout << "Float" << std::endl;
}
void MyFunc(tag<EAnEnum>)
{
std::cout << "Enum" << std::endl;
}
template<typename T>
void MyFunc() {
MyFunc(tag<std::decay_t<T>>{});
}
int main()
{
MyFunc<EAnEnum>();
return 0;
}
您可以轻松添加要转发的参数包到右边 MyFunc
,并且仍然使用此技术来解决您的问题。
当然,您现在可以专注于任何枚举。
您还可以提供后备 MyFunc
作为:
template<typename T>
void MyFunc(tag<T>)
{
std::cout << "Fallback" << std::endl;
}
如果你想回退所有可能的枚举类型,你现在可以依赖 SFINAE,因为这些是不同的重载函数:
template<typename T>
std::enable_if_t<std::is_enum<T>::value>
MyFunc(tag<T>)
{
std::cout << "Fallback for enums only" << std::endl;
}
请注意,您不应直接使用接受 tag
专业化作为入口点的 MyFunc
的含义。
这些是 内部 函数。
请改用通用的,如示例所示。
你不能部分特化一个函数模板,但你能不能让它转发到一个class模板。
因为你的函数没有特别简单的参数:
#include <iostream>
#include <type_traits>
namespace impl {
using namespace std;
template< class Type, bool is_enum_ = is_enum<Type>::value >
struct Foo;
template< class Type >
struct Foo<Type, true>
{ void func() { cout << "Enum" << endl; } };
template<>
struct Foo<int>
{ void func() { cout << "Int" << endl; } };
template<>
struct Foo<float>
{ void func() { cout << "Float" << endl; } };
} // namespace impl
template< class Type >
void foo()
{ impl::Foo<Type>().func(); }
auto main()
-> int
{
enum class An_enum
{
alpha, beta,
};
foo<An_enum>();
foo<int>();
foo<float>();
#ifdef TEST
foo<char>(); //! Doesn't compile.
#endif
}
通过参数,您可以通过 std::forward
.
使用“完美转发”(虽然不是那么完美,但通常足够好)
是否可以在 enum
上特化模板函数?
我注意到 here 如果模板函数不是枚举,则可以将其禁用,但这是否可能同时仍允许其他类型?
我下面的示例显示了 int
、float
和 enum
的特化(它不会编译,因为它试图重载 enum
版本而不是特化它)。我觉得我遗漏了一些明显的东西。
请注意,我希望专注于 any 枚举,而不仅仅是命名枚举(示例中的 EAnEnum
)
#include <iostream>
enum class EAnEnum
{
Alpha,
Beta,
};
template<typename T>
void MyFunc();
template<>
void MyFunc<int>()
{
std::cout << "Int" << std::endl;
}
template<>
void MyFunc<float>()
{
std::cout << "Float" << std::endl;
}
// MyFunc<Enum>
template<typename T>
typename std::enable_if<std::is_enum<T>::value, void>::type MyFunc()
{
std::cout << "Enum" << std::endl;
}
int main()
{
MyFunc<EAnEnum>();
return 0;
}
您不能部分特化一个函数,但您可以使用 标签调度。
它遵循基于 OP 问题的最小工作示例:
#include <iostream>
#include<type_traits>
enum class EAnEnum
{
Alpha,
Beta,
};
template<typename>
struct tag {};
void MyFunc(tag<int>)
{
std::cout << "Int" << std::endl;
}
void MyFunc(tag<float>)
{
std::cout << "Float" << std::endl;
}
void MyFunc(tag<EAnEnum>)
{
std::cout << "Enum" << std::endl;
}
template<typename T>
void MyFunc() {
MyFunc(tag<std::decay_t<T>>{});
}
int main()
{
MyFunc<EAnEnum>();
return 0;
}
您可以轻松添加要转发的参数包到右边 MyFunc
,并且仍然使用此技术来解决您的问题。
当然,您现在可以专注于任何枚举。
您还可以提供后备 MyFunc
作为:
template<typename T>
void MyFunc(tag<T>)
{
std::cout << "Fallback" << std::endl;
}
如果你想回退所有可能的枚举类型,你现在可以依赖 SFINAE,因为这些是不同的重载函数:
template<typename T>
std::enable_if_t<std::is_enum<T>::value>
MyFunc(tag<T>)
{
std::cout << "Fallback for enums only" << std::endl;
}
请注意,您不应直接使用接受 tag
专业化作为入口点的 MyFunc
的含义。
这些是 内部 函数。
请改用通用的,如示例所示。
你不能部分特化一个函数模板,但你能不能让它转发到一个class模板。
因为你的函数没有特别简单的参数:
#include <iostream>
#include <type_traits>
namespace impl {
using namespace std;
template< class Type, bool is_enum_ = is_enum<Type>::value >
struct Foo;
template< class Type >
struct Foo<Type, true>
{ void func() { cout << "Enum" << endl; } };
template<>
struct Foo<int>
{ void func() { cout << "Int" << endl; } };
template<>
struct Foo<float>
{ void func() { cout << "Float" << endl; } };
} // namespace impl
template< class Type >
void foo()
{ impl::Foo<Type>().func(); }
auto main()
-> int
{
enum class An_enum
{
alpha, beta,
};
foo<An_enum>();
foo<int>();
foo<float>();
#ifdef TEST
foo<char>(); //! Doesn't compile.
#endif
}
通过参数,您可以通过 std::forward
.