如何访问C++模板参数?是否有更简洁的实现方式?
问题
我需要在使用某模板的其他模板中获取该模板的参数,请问该如何访问?目前我通过在模板中定义constexpr static size_t data_size的方式实现,这种方法是否为推荐方案?有没有语法可以让data_user_typed无需借助该静态成员就能访问ExtendableIndex中的_data_size?我知道该方式不会增加生成代码的开销,但仍想了解语言层面是否有更直接的实现方法。
示例代码如下:
#include <array> using data_type = int; template<std::size_t _data_size> struct ExtendableIndex { constexpr static std::size_t data_size = _data_size; std::size_t index; std::array<data_type, _data_size> data; }; template<> struct ExtendableIndex<0> { constexpr static std::size_t data_size = 0; std::size_t index; }; constexpr std::size_t cache_length = 0; // Can be set to any cache size including 0 using DefaultIndex = ExtendableIndex<cache_length>; template<std::size_t _data_size> ExtendableIndex<_data_size> data_user() { ExtendableIndex<_data_size> index{}; if constexpr (_data_size > 0) { auto value = index.data[0]; } return index; } template<typename T> T data_user_typed() { T index{}; if constexpr (T::data_size > 0) { auto value = index.data[0]; } return index; } int main() { auto index_one = data_user<cache_length>(); // Works, but requires passing length, not a type auto index_two = data_user<DefaultIndex::data_size>(); // Seems to be better auto index_three = data_user_typed<DefaultIndex>(); // Good, but still requires constexpr static data_size }
解答
1. 模板参数的常规访问方式
要在其他模板中获取目标模板的参数,主流实现方式有两种:类内嵌静态常量(你当前使用的方法)、类型萃取器。
2. 当前方案的合理性
你通过constexpr static size_t data_size暴露模板参数的方式是完全合规且推荐的:它简洁直观,编译期即可获取值,无任何运行时开销,代码可读性强,是C++中暴露模板参数的常规做法之一。
3. 无需内嵌静态成员的直接实现方法
如果不想依赖类内部的静态成员,可以通过模板特化的类型萃取器提取ExtendableIndex的模板参数,这是语言层面更通用的类型元编程技巧:
实现类型萃取器
// 基础模板声明 template<typename T> struct ExtendableIndexTraits; // 针对ExtendableIndex的特化版本 template<std::size_t N> struct ExtendableIndexTraits<ExtendableIndex<N>> { constexpr static std::size_t data_size = N; }; // 便捷的常量别名,简化调用 template<typename T> constexpr std::size_t ExtendableIndexDataSize = ExtendableIndexTraits<T>::data_size;
修改data_user_typed使用萃取器
template<typename T> T data_user_typed() { T index{}; if constexpr (ExtendableIndexDataSize<T> > 0) { auto value = index.data[0]; } return index; }
这种方式的优势:
- 无需修改原
ExtendableIndex的定义,对无法改动的第三方模板同样适用; - 萃取逻辑与类本身解耦,符合单一职责原则;
- 同样是编译期计算,无运行时开销。
另外,在C++20及以上版本,还可以结合概念约束类型,让代码更健壮:
template<typename T> concept IsExtendableIndex = requires { ExtendableIndexTraits<T>::data_size; }; template<IsExtendableIndex T> T data_user_typed() { // 原逻辑保持不变 }
内容的提问来源于stack exchange,提问作者Damir Tenishev
相关产品推荐
相关产品推荐

