最近做cinatra遇到这样的需求,根据一个type来获取对应的第一个元素,需要注意的一个问题是,如果没有这个类型的时候,通过编译期断言提醒使用者,实现代码如下:
1.C++14实现
template <class T, std::size_t N, class... Args> struct indexOf; template <class T, std::size_t N, class... Args> struct indexOf<T, N, T, Args...> { static constexpr auto value = N; }; template <class T, std::size_t N, class U, class... Args> struct indexOf<T, N, U, Args...> { static constexpr auto value = indexOf<T, N + 1, Args...>::value; }; template <class T, std::size_t N> struct indexOf<T, N> { static constexpr auto value = -1; static_assert(value!=-1, "the type is not exist"); }; template <class T, class... Args> T get_element_by_type(const std::tuple<Args...>& t) { return std::get<indexOf<T, 0, Args...>::value>(t); }
2.C++11的实现方法
template <class T, std::size_t N, class... Args> struct indexOf; template <class T, std::size_t N, class... Args> struct indexOf<T, N, T, Args...> { enum { value = N }; }; template <class T, std::size_t N, class U, class... Args> struct indexOf<T, N, U, Args...> { enum { value = indexOf<T, N + 1, Args...>::value}; }; template <class T, std::size_t N> struct indexOf<T, N> { enum { value = -1 }; static_assert(value!=-1, "the type is not exist"); };
把enum换成const int也没问题,如果完全用C++11的方式去做那就用std::integral_constant吧,代码如下:
template <class T, std::size_t N, class... Args> struct indexOf; template <class T, std::size_t N, class... Args> struct indexOf<T, N, T, Args...> : std::integral_constant<int, N> { }; template <class T, std::size_t N, class U, class... Args> struct indexOf<T, N, U, Args...> : std::integral_constant<int, indexOf<T, N + 1, Args...>::value> { }; template <class T, std::size_t N> struct indexOf<T, N> : std::integral_constant < int, -1 > { }; template <class T, class... Args> T get_element_by_type(const std::tuple<Args...>& t) { return std::get<indexOf<T, 0, Args...>::value>(t); }
注意,integral_constant方式,加断言不起作用,不过会返回一个无效的-1,在外层也会出现断言提示,问题不大。
测试代码:
std::tuple<int, double, char, short> tp = std::make_tuple(1, 2.3, 2, 1); //auto r = get_element_by_type<string>(tp); //编译期断言错误 auto r = get_element_by_type<double>(tp); //返回2.3
时间: 2024-10-10 10:39:28