向成员函数添加常量限定符

Adding a const qualifier to a member function

本文关键字:常量 添加 成员 函数      更新时间:2023-10-16

我目前正在编写一个接口类,该接口类应提供对复杂结构的内部元素的访问,作为常量或非常量引用。这个想法是,一些模块被授予 const 访问权限,而一些模块被授予完全访问权限。

我使用"type_traits"'std::add_const' 有条件地限定内部成员函数的返回类型,不幸的是,我想不出一种有条件地将成员函数限定为 const 或 non-const 的方法。

这可能吗?如果是这样,如何?

例如:

template< typename T, bool isConst  >
struct apply_const
{
    typedef T type;
};
template<typename T>
struct apply_const<T, true>
{
    typedef typename std::add_const<T>::type type;
};
template< bool isConst >
const Interface
{
    /// @brief get the TypeA member
    typename apply_const<TypeA, isConst >::type& GetXpo3Container()  // how do I conditionally add a const qualifier
    {
        return config_.type_a_member_;
    }
    typename apply_const<Profile, isConst >::type& GetProfile( unint32_t id )  // qualifier ???
    {
        return config_.profiles.get( id );
    }
    // .... lots more access functions
    ConfigType config_; // the config
};

注意:分离/创建接口的 2 个版本的根本原因是它们将提供对不同config实例的访问 - 一个是可写的,另一个不是。正在开发的子系统是一个嵌入式Netconf Agent,它支持<running><candidate>配置。

这似乎最容易做到专业化:

template< bool isConst >
struct Interface;
template <>
struct Interface<false>
{
    TypeA& GetXpo3Container()
    {
        return config_.type_a_member_;
    }
};
template <>
struct Interface<true>
{
    const TypeA& GetXpo3Container() const
    {
        return config_.type_a_member_;
    }
};

编辑:虽然我不完全确定这增加了什么。拥有不是更容易

struct Interface
{
    TypeA::type& GetXpo3Container()
    {
        return config_.type_a_member_;
    }
    const TypeA::type& GetXpo3Container() const
    {
        return config_.type_a_member_;
    }
};

并在适当的情况下使用const Interface?或者出于其他原因这不是一种选择?

编辑2:我的std::enable_if使用错误,现在已经消失了。

您可以使用 SFINAE:

template<bool isConst>
struct Interface
{
    template<
        bool Cond = isConst
        , typename std::enable_if<!Cond, int>::type = 0            
    >
    TypeA&
    GetXpo3Container() const
    {
        return config_.type_a_member_;
    }
    template<
        bool Cond = isConst
        , typename std::enable_if<Cond, int>::type = 0
    >
    TypeA const&
    GetXpo3Container() const
    {
        return config_.type_a_member_;
    }
};

请注意,这两个成员需要成为模板,并且我使用默认参数来强制typename std::enable_if<Cond, int>::type依赖 - 在类的范围内std::enable_if<isConst, int>::type依赖,因此在类实例化时会解决硬错误,而我们想要SFINAE。

但是,默认参数意味着有人可以执行例如 Interface<true> f; TypeA& ref = f.GetXpo3Container<false>(); .如果你想避免这种情况(例如,你不相信用户不会滥用接口的未指定位),这里有另一种方法可以使std::enable_if的成员type再次依赖,这可能更合适,但更晦涩难懂:

template<typename T, T Value, typename>
struct depend_on_c {
    static constexpr T value = Value;
};
/* and in the scope of Interface: */
    template<
        typename Dummy = void
        , typename std::enable_if<
            depend_on_c<bool, isConst, Dummy>::value
            , int
         >::type = 0
    >
    /* rest as before */
您可以针对

isConst为真的情况专门化模板,并使所有成员函数在这种情况下const,同时将它们保留在主模板中不const

或者,编写成员函数的两个版本(一个const,一个不是),并使用 enable_if 仅启用适当的重载。