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

如何创建检查return语句合法性的C++ concept并实现可透明返回的Box包装类

现有实现的问题

你编写的模板构造函数没有排除参数为Box<T>本身的场景:当尝试拷贝/移动Box<T>实例时,泛型构造函数的转发引用优先级高于编译器默认生成的拷贝/移动构造,会被优先匹配,此时会尝试用Box<T>类型去构造内部的T成员,自然编译失败。

最优实现方案(C++17及以上)

如果你使用C++17及以上版本,零自定义构造函数的聚合类方案完全满足需求,也是构造函数最少的实现:

template <typename T>
struct Box {
    T t;
};

该方案的原理:

  • 没有自定义构造函数,属于聚合类,符合C++17的拷贝列表初始化规则,所有能用来初始化T的返回表达式,都可以直接用来初始化Box<T>
  • 编译器自动生成的拷贝、移动、析构函数全部符合预期,无需额外编码
  • 支持所有返回场景:
    // 单值返回
    Box<std::string> get_str() { return "hello world"; } // 编译通过
    // 初始化列表返回
    Box<std::pair<int, int>> get_pair() { return {1, 2}; } // 编译通过
    // 拷贝返回
    Box<int> b{42};
    Box<int> get_box() { return b; } // 编译通过
    

兼容低版本C的实现(C11及以上)

如果需要兼容C++11/14,或者需要添加自定义封装逻辑必须编写构造函数,可以修正原实现,显式声明拷贝/移动构造避免泛型构造抢匹配,同时在约束中排除Box<T>自身类型的参数:

template <typename T>
class Box {
public:
    Box(const Box&) = default;
    Box(Box&&) = default;

    template <typename... Ts>
    constexpr Box(Ts&&... ts)
    noexcept(std::is_nothrow_constructible_v<T, Ts...>)
    : t(std::forward<Ts>(ts)...)
    {
        static_assert(
            sizeof...(Ts) != 1 || !std::is_same<Box, typename std::decay<Ts...>::type>::value,
            "Invalid parameter type"
        );
        static_assert(
            std::is_constructible<T, Ts...>::value,
            "T cannot be constructed from given parameters"
        );
    }

private:
    T t;
};

如果使用C++20,可以把static_assert替换为concept约束,写法更简洁:

template <typename T>
class Box {
public:
    Box(const Box&) = default;
    Box(Box&&) = default;

    template <typename... Ts>
    requires (
        (sizeof...(Ts) != 1 || !std::same_as<Box, std::decay_t<Ts>>) &&
        std::constructible_from<T, Ts...>
    )
    constexpr Box(Ts&&... ts)
    noexcept(std::is_nothrow_constructible_v<T, Ts...>)
    : t(std::forward<Ts>(ts)...)
    {}

private:
    T t;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 03:54:05