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

如何在C++17之前版本中实现propagation_const?

在C++17之前实现const传播的propagation_const

在你的代码中,const A对象调用bar()时,成员b_是const std::shared_ptr<B>——但shared_ptr的const仅限制指针本身不能被重新赋值,不会影响它指向的对象的const属性,因此b_->foo()会调用非const版本的foo()。要实现const传播(即宿主对象是const时,通过内部指针访问到的对象也被视为const),我们可以手动实现一个propagation_const模板类,在C++17之前模拟这一行为。

实现思路

核心是通过重载const和非const版本的operator->、operator*以及get()方法,根据当前propagation_const对象的const属性,返回对应限定类型的指针/引用:

  • 当对象是非const时,直接返回内部指针的原生访问结果;
  • 当对象是const时,返回指向const元素的指针/引用,强制后续成员函数调用匹配const版本。

完整实现代码

#include <iostream>
#include <memory>
#include <type_traits>

template <typename T>
class propagation_const {
public:
    // 转发构造参数给内部指针
    template <typename... Args>
    propagation_const(Args&&... args) : ptr_(std::forward<Args>(args)...) {}

    // 非const版本:返回原生指针
    typename std::pointer_traits<T>::pointer operator->() {
        return ptr_.operator->();
    }

    // const版本:返回指向const元素的指针
    typename std::add_const<typename std::pointer_traits<T>::element_type>::type* operator->() const {
        return ptr_.operator->();
    }

    // 非const版本:返回原生引用
    typename std::pointer_traits<T>::reference operator*() {
        return *ptr_;
    }

    // const版本:返回const元素的引用
    typename std::add_const<typename std::pointer_traits<T>::element_type>::type& operator*() const {
        return *ptr_;
    }

    // 获取内部指针的非const版本
    typename std::pointer_traits<T>::pointer get() {
        return ptr_.get();
    }

    // 获取内部指针的const版本
    typename std::add_const<typename std::pointer_traits<T>::element_type>::type* get() const {
        return ptr_.get();
    }

private:
    T ptr_;
};

class B {
public:
    void foo() const {
        std::cout << "foo const" << std::endl;
    }
    void foo() {
        std::cout << "foo non-const" << std::endl;
    }
};

class A {
public:
    void bar() const {
        std::cout << "bar const" << std::endl;
        b_->foo(); // 此时b_->是const B*,调用const版本foo
    }
    void bar() {
        std::cout << "bar non-const" << std::endl;
        b_->foo(); // 此时b_->是B*,调用非const版本foo
    }
    propagation_const<std::shared_ptr<B>> b_{std::make_shared<B>()};
};

int main() {
    const A a;
    a.bar(); // 输出:bar const\nfoo const

    A a_nonconst;
    a_nonconst.bar(); // 输出:bar non-const\nfoo non-const
}

效果说明

  • 当使用const A对象调用bar()时,b_作为const成员,其operator->返回const B*,因此会触发B::foo() const;
  • 当使用非constA对象时,operator->返回B*,正常调用非const版本的foo()。

这个实现兼容常见的智能指针(如std::shared_ptr、std::unique_ptr)和原始指针,满足C++17之前的标准要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:53:11