如何使用C++模板创建具有任意数量案例的开关语句生成器
How can I create a switch statement generator with an arbitrary number of cases using C++ templates?
switch语句可能很长,所以我写了下面的类(在main((中提供了示例用法(:
#include <iostream>
using namespace std;
template <typename In, typename Out, In In1, Out Out1, In In2, Out Out2, Out DefaultOut>
struct SwitchMap
{
Out operator[](const In& input) const
{
switch (input) {
case In1: return Out1;
case In2: return Out2;
default: return DefaultOut;
}
}
};
int main(int, char **)
{
SwitchMap<unsigned int, unsigned int, 3, 1, 4, 2, 3> myMap;
cout << myMap[3] << endl; // prints 1
cout << myMap[4] << endl; // prints 2
cout << myMap[5] << endl; // prints 3
return 0;
}
我想实现两个目标:1. 我想让 SwitchMap 接受任意数量的情况(其中 Outs 的数量比 Ins 的数量大 1,以提供默认返回值(。我的示例仅适用于两个 Ins、两个 Out 和一个默认 Out。2. 是否可以使map
的声明看起来像这样:SwitchMap<3, 1, 4, 2, 3> myMap;
?如果可以自动推断类型,那就太好了(尽管我意识到这可能会导致编译器选择int
而不是我愿意处理的unsigned int
(。
我能否实现其中一个或两个目标?
下面是一个使用 if 语句的示例。请注意,一个好的编译器将生成与开关一样高效的代码。结果也是 constexpr。
#include <iostream>
template <typename T, T DEF>
inline constexpr T SwitchMap_helper(T) {
return DEF;
}
template <typename T, T IN, T OUT, T... REST>
inline constexpr T SwitchMap_helper(T v) {
return v == IN ? OUT : SwitchMap_helper<T, REST...>(v);
}
template <typename T, T... CASES>
struct SwitchMap {
constexpr T operator[](T v) {
return SwitchMap_helper<T, CASES...>(v);
}
};
int
main() {
SwitchMap<int, 1, 2, 3, 4, 5> sm1;
std::cout << sm1[1] << std::endl;
std::cout << sm1[3] << std::endl;
std::cout << sm1[10] << std::endl;
}
下面是一个对函数模板使用间接寻址的小解决方法:
#include<tuple>
#include<iostream>
template<typename ... Args>
struct SwitchMap
{
static const size_t ArgsSize = sizeof ... (Args);
using ArgsTuple = std::tuple<Args ...>;
using InType = typename std::tuple_element<0,ArgsTuple>::type;
using OutType = typename std::tuple_element<1,ArgsTuple>::type;
std::tuple<Args ...> t;
SwitchMap(Args const& ... args) : t(std::make_tuple(args ...))
{
static_assert((ArgsSize & 1) && (ArgsSize > 2), " ");
//here possibly add another check for the consistency of the input types
}
template<int> struct int2type{};
template<int N>
OutType get(InType const& in, int2type<N>) const
{
return in == std::get<N>(t) ? std::get<N+1>(t) : get(in,int2type<N+2>());
}
OutType get(InType const& in, int2type<ArgsSize-1>) const
{
return std::get<ArgsSize-1>(t);
}
OutType operator[](InType const& in) const
{
return get(in,int2type<0>());
}
};
template<typename ... Args>
auto makeSwitchMap(Args const& ... args)
{
return SwitchMap<Args ...>(args ...);
}
通过调用它
int main()
{
auto switchMap = makeSwitchMap(1,std::string("Say Hi"),2,std::string("Say Goodbye"),std::string("Say nothing"));
std::cout<<switchMap[1]<<std::endl;
std::cout<<switchMap[2]<<std::endl;
std::cout<<switchMap[4]<<std::endl;
}
产生
Say Hi
Say Goodbye
Say nothing
演示
相关文章:
- C 和 C++ 中开关语句的案例标签的常量值,但显示不同的行为
- 正在读取开关案例中的.txt文件
- C++实用程序,用于将长开关语句转换为封装开关案例阶梯的简洁函数调用
- 执行默认值:在C 中的开关案例选择语句中
- 在开关案例节点中,将const int int指向int
- 使用开关语句案例中的随机数
- 案例和开关问题
- 如何在 c++ 中使用开关中的案例条件作为变量
- 如果使用较小的数字,则开关案例更快
- 我可以在c 中的语句中使用开关案例的情况吗?
- 没有默认标签的开关案例中的无效值
- 在开关案例内将字符串化
- 如何从案例 4 调用开关案例 5
- 状态机:使用转换矩阵而不是嵌套的开关案例C++
- 在 c++ 开关案例中引入循环
- C++、开关案例和编译器
- 新设置开关案例arduino
- 在开关案例语句中,它说"duplicate case value"出现错误。有人知道为什么吗?
- C++中的动态开关案例
- 抽象/重构此开关/案例的好方法是什么?