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

基于移动语义的线性链式工厂编译错误修复求助

修复线性链式工厂的编译错误与逻辑问题

首先,我们来拆解你遇到的编译错误:

error: cannot bind rvalue reference of type 'B_maker&&'to lvalue of type 'B_maker'return Exp<A_maker, T>(std::move(*this), other_maker); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

这个错误的核心是完美转发失效:A_maker::operator^接收的other_maker虽然是右值引用模板参数,但参数本身在函数内是左值,直接传给Exp构造函数(期望右值引用)时无法绑定。除此之外,你的代码还有多处逻辑问题,比如Exp::make()调用成员的方式错误、append方法的嵌套构造逻辑错误、make_now_的访问权限问题等,下面是完整的修复方案:


第一步:修复编译错误(完美转发参数)

修改A_maker::operator^,使用std::forward保留参数的右值属性,同时用std::remove_reference_t处理模板类型,避免引用类型被存储到Exp中:

template<typename T>
auto operator^(T&& other_maker) {
    return Exp<A_maker, std::remove_reference_t<T>>(
        std::move(*this), 
        std::forward<T>(other_maker)  // 完美转发,保留右值属性
    );
}

第二步:修复Exp::make()的逻辑错误

原代码中rest_.syn(top_.syn)是错误的——syn是成员函数而非成员变量,我们需要把top_.make()生成的对象传递给rest_.syn:

auto make() {
    return rest_.syn(top_.make());
}

第三步:修复Exp::append()的嵌套构造逻辑

原append方法的Exp构造方式错误,需要正确嵌套表达式对象,同时继续使用完美转发传递新工厂:

template<typename New_maker>
auto append(New_maker&& new_maker) {
    return Exp<Exp<Top, Rest>, std::remove_reference_t<New_maker>>(
        std::move(*this), 
        std::forward<New_maker>(new_maker)
    );
}

同时调整Exp::operator^的判断逻辑,改用公共接口访问make_now_(避免私有成员访问问题):

template<typename Maker>
auto operator^(Maker&& m) {
    if (m.is_make_now()) {
        return m.syn(make());
    } else {
        return append(std::forward<Maker>(m));
    }
}

第四步:修复B_maker的访问权限与make()方法

为B_maker添加公共接口is_make_now()供Exp访问,同时限制make()仅能被右值调用(避免悬垂引用):

template<typename P=A>
class B_maker {
    using self_type = B_maker<P>;
public:
    explicit B_maker(int val) : val_(val) {}
    
    // 仅允许右值对象调用make()
    self_type make() && {
        make_now_ = true;
        return std::move(*this);
    }

    // 公共接口,让Exp判断是否立即创建
    bool is_make_now() const { return make_now_; }

private:
    B<P> syn(P&& p) { return B(std::move(p), val_); }
    bool make_now_{false};
    int val_;
    template<typename T, typename R> friend class Exp;
};

第五步:支持B<B<A>>的嵌套生成

修复后的代码已经支持嵌套链式调用,比如A_maker(0) ^ B_maker<>(1) ^ B_maker<B<A>>(2).make()会生成B<B<A>>对象,核心是Exp::make()的递归调用逻辑会逐层传递前序工厂的生成结果。


完整修复后的代码

#include <iostream>
#include <utility>
#include <type_traits>

struct A { 
    explicit A(int val) : val_(val) {} 
    int val_{-1};
};

template<typename P=A>
struct B { 
    B(P&& p, int val) : p_(std::move(p)), val_(val) {} 
    P p_; 
    int val_{-1};
};

template<typename Top, typename Rest>
class Exp { 
public: 
    Exp(Top&& top, Rest&& rest) 
        : top_(std::move(top)), rest_(std::move(rest)) {} 

    template<typename Maker>
    auto operator^(Maker&& m) {
        if (m.is_make_now()) {
            return m.syn(make());
        } else {
            return append(std::forward<Maker>(m));
        }
    } 

    auto make() {
        return rest_.syn(top_.make());
    } 

private: 
    template<typename New_maker>
    auto append(New_maker&& new_maker) {
        return Exp<Exp<Top, Rest>, std::remove_reference_t<New_maker>>(
            std::move(*this), 
            std::forward<New_maker>(new_maker)
        );
    } 

    Top top_; 
    Rest rest_;
};

class A_maker { 
public: 
    explicit A_maker(int val) : val_(val) {} 

    auto make() {
        return syn();
    } 

    template<typename T>
    auto operator^(T&& other_maker) {
        return Exp<A_maker, std::remove_reference_t<T>>(
            std::move(*this), 
            std::forward<T>(other_maker)
        );
    } 

private: 
    A syn() { return A(val_); } 
    int val_; 
    template<typename T, typename R> friend class Exp;
};

template<typename P=A>
class B_maker { 
    using self_type = B_maker<P>;
public: 
    explicit B_maker(int val) : val_(val) {} 

    self_type make() && {
        make_now_ = true;
        return std::move(*this);
    }

    bool is_make_now() const { return make_now_; }

private: 
    B<P> syn(P&& p) { return B(std::move(p), val_); } 
    bool make_now_{false}; 
    int val_; 
    template<typename T, typename R> friend class Exp;
};

int main() { 
    // 基础场景测试
    B bba(B(A(0), 1), 2); 
    auto x = A_maker(0) ^ B_maker(1).make(); 
    std::cout << x.p_.val_ << ", " << x.val_ << std::endl; // 输出:0, 1

    // 嵌套B<B<A>>场景测试
    auto y = A_maker(0) ^ B_maker<>(1) ^ B_maker<B<A>>(2).make();
    std::cout << y.p_.p_.val_ << ", " << y.p_.val_ << ", " << y.val_ << std::endl; // 输出:0, 1, 2
    return 0;
}

关于反向传递需求的实现思路

如果要实现后续工厂的需求反向传递给前置工厂,你可以:

  • 为每个工厂添加类型特征(比如required_arg_type),标记该工厂需要的前置参数类型
  • 在Exp的make()过程中,递归地让前置工厂根据后续工厂的类型特征调整创建逻辑
  • 例如B_maker<B<A>>需要B<A>作为参数,前置的B_maker需要动态生成B<A>而非默认的B

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:08:20