You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++20实现概念约束:结构体非静态公有成员均为非const引用

实现C++20概念约束结构体所有非静态公有数据成员为非const引用

核心思路说明

标准C20本身没有内置机制可以枚举任意类型的所有非静态公有数据成员,因此我们需要针对聚合类型(满足C聚合体定义的结构体/类)来实现约束——因为聚合体的非静态数据成员均为公有,且可通过编译器扩展或结构化绑定技巧访问成员类型。

依赖编译器扩展的实现(GCC/Clang)

如果可以接受GCC/Clang的编译器扩展,我们可以利用__builtin_member_count获取聚合体的成员数量,结合模板元编程检查每个成员类型是否为非const左值引用:

代码实现

#include <type_traits>
#include <utility>

// 检查单个类型是否为非const左值引用
template<typename T>
constexpr bool is_non_const_lvalue_reference_v = 
    std::is_lvalue_reference_v<T> && 
    !std::is_const_v<std::remove_reference_t<T>>;

// 递归检查tuple的所有元素是否符合非const左值引用要求
template<typename Tuple>
struct all_non_const_refs : std::true_type {};

template<typename First, typename... Rest>
struct all_non_const_refs<std::tuple<First, Rest...>> : 
    std::bool_constant<is_non_const_lvalue_reference_v<First> && all_non_const_refs<std::tuple<Rest...>>::value> {};

template<typename Tuple>
constexpr bool all_non_const_refs_v = all_non_const_refs<Tuple>::value;

// 利用GCC扩展获取聚合体的成员类型tuple
template<typename T>
constexpr auto get_member_types() {
    if constexpr (std::is_aggregate_v<T>) {
        return []<std::size_t... Is>(std::index_sequence<Is...>) {
            return std::tuple<std::decay_t<decltype(std::get<Is>(std::declval<T>()))>...>();
        }(std::make_index_sequence<__builtin_member_count(T)>());
    } else {
        return std::tuple<>();
    }
}

template<typename T>
using member_types_t = decltype(get_member_types<T>());

// 主判断trait
template<typename T>
constexpr bool isStructOfNonConstReferences_v = 
    std::is_aggregate_v<T> && 
    all_non_const_refs_v<member_types_t<T>>;

// C++20概念定义
template<typename T>
concept StructOfNonConstReferences = isStructOfNonConstReferences_v<T>;

// 测试示例
struct A
{
    int& i;
    std::string& s;
};

struct B
{
    int& i;
    std::string& s;
    void foo() { s = std::to_string(i); }
};

struct C
{
    int i;
    std::string& s;
};

struct D
{
    const int& i;
    const std::string& s;
};

static_assert(isStructOfNonConstReferences<A>);
static_assert(isStructOfNonConstReferences<B>);
static_assert(!isStructOfNonConstReferences<C>);
static_assert(!isStructOfNonConstReferences<D>);

纯标准C++20的受限实现

如果必须使用纯标准C++20,我们只能通过结构化绑定的重载来支持有限数量的成员(比如最多支持10个成员),手动处理不同成员数量的情况:

代码实现

#include <type_traits>

// 检查单个类型是否为非const左值引用
template<typename T>
constexpr bool is_non_const_lvalue_reference_v = 
    std::is_lvalue_reference_v<T> && 
    !std::is_const_v<std::remove_reference_t<T>>;

// 检查空结构体
template<typename T>
constexpr bool check_members(T) requires (std::is_aggregate_v<T>) {
    return true;
}

// 检查1个成员的情况
template<typename T>
constexpr bool check_members(T t) requires requires {
    auto [a] = t;
    requires is_non_const_lvalue_reference_v<decltype(a)>;
} {
    auto [a] = t;
    return true;
}

// 检查2个成员的情况
template<typename T>
constexpr bool check_members(T t) requires requires {
    auto [a, b] = t;
    requires is_non_const_lvalue_reference_v<decltype(a)> && is_non_const_lvalue_reference_v<decltype(b)>;
} {
    auto [a, b] = t;
    return true;
}

// 可继续添加3个、4个...成员的检查重载,直到满足需求上限

// 主判断trait
template<typename T>
constexpr bool isStructOfNonConstReferences_v = 
    std::is_aggregate_v<T> && 
    check_members(std::declval<T>());

// C++20概念定义
template<typename T>
concept StructOfNonConstReferences = isStructOfNonConstReferences_v<T>;

// 测试示例
struct A { int& i; std::string& s; };
struct B { int& i; std::string& s; void foo() {} };
struct C { int i; std::string& s; };
struct D { const int& i; const std::string& s; };

static_assert(isStructOfNonConstReferences<A>);
static_assert(isStructOfNonConstReferences<B>);
static_assert(!isStructOfNonConstReferences<C>);
static_assert(!isStructOfNonConstReferences<D>);

关键注意事项

  1. 上述实现仅针对聚合类型:如果结构体包含私有/保护数据成员、用户声明的构造函数或基类,则不属于聚合体,无法被正确检查。
  2. 成员函数不影响检查结果:符合示例中结构体B的情况,因为我们只约束数据成员的类型。
  3. 空结构体默认符合条件:根据逻辑,空结构体没有违反约束的成员,因此isStructOfNonConstReferences_v会返回true,如果需要排除空结构体,可以在trait中添加std::tuple_size_v<member_types_t<T>> > 0的判断。

内容的提问来源于stack exchange,提问作者PluginPenguin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 10:57:03