是否可以在enum
上专门化模板功能?
我已经注意到here如果模板功能不是枚举,则可以禁用模板功能,但是这仍然可以允许其他类型吗?
下面的示例显示了int
,float
和enum
的特化(它没有编译,因为它试图重载enum
版本而不是专门化它)。我觉得我错过了一些明显的东西。
请注意,我希望专注于任何枚举,而不仅仅是命名的(示例中为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;
}
答案 0 :(得分:3)
您无法对功能进行部分专业化,但您可以使用标签调度。 它遵循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;
}
请注意,您不应直接使用接受MyFunc
专业化的tag
作为切入点的含义。
这些是内部功能
请使用通用的,如示例所示。
答案 1 :(得分:2)
您不能部分专门化功能模板,但是您可以将其转发到类模板。
由于你的函数没有特别容易的参数:
#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
使用“完美转发”(这不是完美的,真的,但通常足够好)。