如何简化获取类/结构体静态成员的Type Trait定义?
通用型静态成员获取Type Trait实现方案
你需要实现一个Type Trait,当类型T中存在指定静态成员时返回其值,否则返回默认值。现有针对静态成员X的实现如下,但针对其他成员(如Y)需要重复编写大量代码,希望找到更简便的通用方案:
// we define our type trait here template<typename T> struct get_X { static constexpr int value = -1; }; // and a specialization for types holding the required member template<typename T> static constexpr bool has_X = requires { T::X; }; template<typename T> requires(has_X<T>) struct get_X<T> { static constexpr int value = T::X; }; struct foo { static constexpr int X = 3; }; struct bar { static constexpr int Y = 5; }; static_assert (get_X<foo>::value == 3); static_assert (get_X<bar>::value == -1); int main() {}
通用化实现方案
可以通过模板非类型参数结合C++20的requires表达式,实现一套通用的Type Trait,无需为每个静态成员重复编写代码:
方案1:结构体形式的通用Trait
这种形式保留了传统Type Trait的结构体风格,适合需要在模板元编程中复用的场景:
#include <type_traits> // 通用检测模板:判断类型T是否包含指定静态成员 template<typename T, auto Member> static constexpr bool has_static_member = requires { Member; }; // 通用Trait:获取静态成员值,不存在则返回默认值 template<typename T, auto Member, auto DefaultValue> struct get_static_member { static constexpr auto value = DefaultValue; }; // 特化版本:当存在目标静态成员时返回其值 template<typename T, auto Member, auto DefaultValue> requires has_static_member<T, Member> struct get_static_member<T, Member, DefaultValue> { static constexpr auto value = Member; }; // 示例用法 struct foo { static constexpr int X = 3; }; struct bar { static constexpr int Y = 5; }; // 获取foo的X成员,默认值-1 static_assert(get_static_member<foo, &foo::X, -1>::value == 3); // 获取bar的X成员(不存在),返回默认值-1 static_assert(get_static_member<bar, &bar::X, -1>::value == -1); // 获取foo的Y成员(不存在),返回默认值0 static_assert(get_static_member<foo, &foo::Y, 0>::value == 0); // 获取bar的Y成员,默认值0 static_assert(get_static_member<bar, &bar::Y, 0>::value == 5); int main() {}
方案2:constexpr函数形式(更简洁)
如果不需要结构体形式的Trait,直接用constexpr函数实现会更紧凑,调用也更直观:
#include <type_traits> // 通用静态成员获取函数 template<typename T, auto Member, auto Default> constexpr auto get_static_member() { if constexpr (requires { Member; }) { return Member; } else { return Default; } } // 示例用法 struct foo { static constexpr int X = 3; }; struct bar { static constexpr int Y = 5; }; static_assert(get_static_member<foo, &foo::X, -1>() == 3); static_assert(get_static_member<bar, &bar::X, -1>() == -1); static_assert(get_static_member<foo, &foo::Y, 0>() == 0); static_assert(get_static_member<bar, &bar::Y, 0>() == 5); int main() {}
方案优势
- 通用性:一套代码支持任意静态成员的获取,无需为每个成员(X、Y等)重复定义
has_XXX、get_XXX这类专属模板 - 灵活性:可以自定义默认值的类型和数值,适配不同成员的类型需求
- 可读性:代码结构清晰,复用性强,减少冗余代码
内容的提问来源于stack exchange,提问作者abcdefg
相关产品推荐
相关产品推荐

