如何基于模板类型为static constexpr成员变量赋值?
基于模板类型为类的static constexpr成员变量赋值的优化方案
我想根据模板类型给类的static constexpr成员变量赋值,目前找到了下面的实现方案,但觉得它不够优雅,尤其是需要支持更多类型的时候嵌套会越来越复杂。能不能用constexpr映射这类方案来实现?我可以使用STL或者Boost库。
#include <iostream> #include <string_view> template <typename T> struct Example { static constexpr std::string_view s{std::is_same_v<T, int> ? "int" : (std::is_same_v<T, double> ? "double" : "other")}; }; int main() { const Example<int> example; std::cout << example.s << std::endl; return 0; }
优化方案
1. 模板特化(STL原生最直接方案)
如果只是映射类型到固定值,模板特化比嵌套三元表达式可读性强得多,扩展类型时只需新增特化块,逻辑清晰:
#include <iostream> #include <string_view> // 基础模板,默认值 template <typename T> struct Example { static constexpr std::string_view s = "other"; }; // int类型特化 template <> struct Example<int> { static constexpr std::string_view s = "int"; }; // double类型特化 template <> struct Example<double> { static constexpr std::string_view s = "double"; }; // 新增类型只需加特化,比如float template <> struct Example<float> { static constexpr std::string_view s = "float"; }; int main() { std::cout << Example<int>::s << std::endl; // 输出int std::cout << Example<double>::s << std::endl; // 输出double std::cout << Example<char>::s << std::endl; // 输出other return 0; }
2. C++20 constexpr映射表
如果想集中管理类型与值的对应关系,可以利用C++20的std::tuple和constexpr函数实现编译时查找,新增类型只需修改映射表:
#include <iostream> #include <string_view> #include <tuple> #include <type_traits> // 编译时类型-值映射表 constexpr auto type_map = std::make_tuple( std::pair<int, std::string_view>{"int"}, std::pair<double, std::string_view>{"double"}, std::pair<float, std::string_view>{"float"} ); // 编译时查找函数 template <typename T> constexpr std::string_view find_type_name() { for (std::size_t i = 0; i < std::tuple_size_v<decltype(type_map)>; ++i) { using PairType = std::tuple_element_t<i, decltype(type_map)>; if constexpr (std::is_same_v<T, typename PairType::first_type>) { return std::get<i>(type_map).second; } } return "other"; } template <typename T> struct Example { static constexpr std::string_view s = find_type_name<T>(); }; int main() { std::cout << Example<int>::s << std::endl; // 输出int std::cout << Example<double>::s << std::endl; // 输出double std::cout << Example<char>::s << std::endl; // 输出other return 0; }
3. Boost.Mp11简化编译时查找(可用Boost时)
Boost.Mp11提供了更简洁的编译时元编程工具,适合复杂场景下的类型映射:
#include <iostream> #include <string_view> #include <boost/mp11/mp_map.hpp> #include <boost/mp11/mp_find.hpp> #include <boost/mp11/mp_at.hpp> // 定义编译时映射表 using type_map = boost::mp11::mp_map< boost::mp11::mp_pair<int, std::string_view>, boost::mp11::mp_pair<double, std::string_view>, boost::mp11::mp_pair<float, std::string_view> >; template <typename T> struct Example { // 查找对应值,找不到返回默认"other" static constexpr std::string_view s = boost::mp11::mp_find<type_map, T>::value == boost::mp11::mp_size<type_map>::value ? "other" : boost::mp11::mp_at<type_map, T>::value; }; // 给映射表中的类型赋值 template <> constexpr std::string_view boost::mp11::mp_at<type_map, int>::value = "int"; template <> constexpr std::string_view boost::mp11::mp_at<type_map, double>::value = "double"; template <> constexpr std::string_view boost::mp11::mp_at<type_map, float>::value = "float"; int main() { std::cout << Example<int>::s << std::endl; // 输出int std::cout << Example<double>::s << std::endl; // 输出double std::cout << Example<char>::s << std::endl; // 输出other return 0; }
方案对比
- 模板特化:最直观,无需额外依赖,适合类型数量不多或需要为特定类型单独定制逻辑的场景。
- C++20 constexpr映射:集中管理对应关系,新增类型只需修改映射表,适合类型较多的场景。
- Boost.Mp11:语法更简洁,编译时元编程功能强大,适合复杂编译时逻辑需求。
内容的提问来源于stack exchange,提问作者peter55555
相关产品推荐
相关产品推荐

