C++ 将字符串和枚举映射到模板化类型
我的函数foo接受两个参数——一个字符串str和一个强类型enum ENUM1。它应该实例化一个类模板,其模板参数依赖于str和ENUM1。如何在不使用以下多个if..then..else语句的情况下实现这一点C++ 将字符串和枚举映射到模板化类型,c++,templates,c++11,enums,C++,Templates,C++11,Enums,我的函数foo接受两个参数——一个字符串str和一个强类型enum ENUM1。它应该实例化一个类模板,其模板参数依赖于str和ENUM1。如何在不使用以下多个if..then..else语句的情况下实现这一点 void foo(std::string str, ENUM1 enumVal) { if (str == "str1" && enumVAL == ENUM1::VAL1) ExampleClass<STR1TYPE, VAL1TYP
void foo(std::string str, ENUM1 enumVal) {
if (str == "str1" && enumVAL == ENUM1::VAL1)
ExampleClass<STR1TYPE, VAL1TYPE> instance;
else if (str == "str1" && enumVAL == ENUM1::VAL2)
ExampleClass<STR1TYPE, VAL2TYPE> instance;
else if (str == "str2" && enumVAL == ENUM1::VAL1)
ExampleClass<STR2TYPE, VAL1TYPE> instance;
...
}
void foo(std::string str,ENUM1 enumVal){
if(str==“str1”&&enumVAL==ENUM1::VAL1)
示例类实例;
else if(str==“str1”&&enumVAL==ENUM1::VAL2)
示例类实例;
else if(str==“str2”&&enumVAL==ENUM1::VAL1)
示例类实例;
...
}
我无法更改ExampleClass的设计方式,也无法更改传入的参数类型。我讨厌if-then-else对于两个参数值的所有排列
我想保留一个std::unordered_map
,但这意味着需要占用内存来保存代码的可读性
有没有更好的方法可以做到这一点?好吧,这是一个模板和类型特征的小例子 首先-单箱的功能对您来说非常有用:
template <typename StrType, typename EnumType>
void fooSingleCase()
{
std::cout << "In: " << __PRETTY_FUNCTION__ << "\n";
ExampleClass<StrType, EnumType> instance;
// ...
}
还有一些例子:
template <>
const std::string StrTraits<STR1TYPE>::pattern = "str1";
template <>
const std::string StrTraits<STR2TYPE>::pattern = "str2";
template <>
const ENUM1 ENUM1Traits<VAL1TYPE>::pattern = ENUM1::VAL1;
template <>
const ENUM1 ENUM1Traits<VAL2TYPE>::pattern = ENUM1::VAL2;
template <>
const ENUM1 ENUM1Traits<VAL3TYPE>::pattern = ENUM1::VAL3;
模板
const std::string StrTraits::pattern=“str1”;
模板
const std::string StrTraits::pattern=“str2”;
模板
常量ENUM1 ENUM1Traits::pattern=ENUM1::VAL1;
模板
常量ENUM1 ENUM1Traits::pattern=ENUM1::VAL2;
模板
常量ENUM1 ENUM1Traits::pattern=ENUM1::VAL3;
所以-我们几乎完成了。我们现在需要让模板变魔术: 首先-假设您已经获得EnumType-只需选择strType-因此-开始使用traits:
template <typename EnumType>
void fooFixedEnumCase(std::string strVal)
{
std::cout << strVal << " not found!\n";
}
template <typename EnumType, typename Str1Type, typename ...StrType>
void fooFixedEnumCase(std::string strVal)
{
if (StrTraits<Str1Type>::pattern == strVal)
fooSingleCase<EnumType, Str1Type>();
else
fooFixedEnumCase<EnumType, StrType...>(strVal);
}
模板
void fooFixedEnumCase(std::string strVal)
{
std::cout切换到unordered_map
只是用堆内存换取代码大小-您当前的硬编码方法会导致额外的可执行文件大小。其中一个可能会稍微小一些,但除非您处于内存严重受限的环境中,否则这种差异不应该让您太担心。实际上,内存占用率所以目前,我已经使用if-then-elses实现了,并且正在寻找一个更智能、更可读的实现。
template <>
const std::string StrTraits<STR1TYPE>::pattern = "str1";
template <>
const std::string StrTraits<STR2TYPE>::pattern = "str2";
template <>
const ENUM1 ENUM1Traits<VAL1TYPE>::pattern = ENUM1::VAL1;
template <>
const ENUM1 ENUM1Traits<VAL2TYPE>::pattern = ENUM1::VAL2;
template <>
const ENUM1 ENUM1Traits<VAL3TYPE>::pattern = ENUM1::VAL3;
template <typename EnumType>
void fooFixedEnumCase(std::string strVal)
{
std::cout << strVal << " not found!\n";
}
template <typename EnumType, typename Str1Type, typename ...StrType>
void fooFixedEnumCase(std::string strVal)
{
if (StrTraits<Str1Type>::pattern == strVal)
fooSingleCase<EnumType, Str1Type>();
else
fooFixedEnumCase<EnumType, StrType...>(strVal);
}
template <typename ...EnumType>
struct Enum1Switch;
template <typename EnumType1, typename ...EnumType>
struct Enum1Switch<EnumType1, EnumType...>
{
template <typename ...StrType>
static void strSwitch(std::string str, ENUM1 enumVal)
{
if (ENUM1Traits<EnumType1>::pattern == enumVal)
fooFixedEnumCase<EnumType1, StrType...>(str);
else
Enum1Switch<EnumType...>::template strSwitch<StrType...>(str, enumVal);
}
};
template <>
struct Enum1Switch<>
{
template <typename ...StrType>
static void strSwitch(std::string str, ENUM1 enumVal)
{
std::cout << static_cast<int>(enumVal) << " not found!\n";
}
};
void foo(std::string str, ENUM1 enumVal) {
Enum1Switch<VAL1TYPE, VAL2TYPE, VAL3TYPE>
::strSwitch<STR1TYPE, STR2TYPE>(str, enumVal);
}
template <>
const std::string StrTraits<STRTYPENEW>::pattern = "newstr";
template <>
const ENUM1 ENUM1Traits<VALTYPENEW>::pattern = ENUM1::NEW_VAL;
void foo(std::string str, ENUM1 enumVal) {
Enum1Switch<VAL1TYPE, VAL2TYPE, VAL3TYPE, VALTYPENEW>
// ^^^^^^^^^^^^
::strSwitch<STR1TYPE, STR2TYPE, STRTYPENEW>(str, enumVal);
// ^^^^^^^^^^^^
}