Adding a const qualifier to a member function

白昼怎懂夜的黑 提交于 2021-01-27 05:39:40

问题


I am currently writing an interface class that should provide access to to internal elements of a complex structure as const or non-const references. The idea is that some modules are granted const access and some modules are granted full access.

I have used the 'type_traits' 'std::add_const' to conditionally qualify the return type of the internal member functions, unfortunately I cannot think of a way of conditionally qualifiying the member functions as const or non-const.

Is this even possible? if so how?

E.G:

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
};

Note: the underlying reason for separating / creating 2 versions of the interface is that they will be providing access to different instances of config - one which is writable and one which is not. The sub-system being developed is an embedded Netconf Agent, which supports <running> and <candidate> configurations.


回答1:


This seems easiest to do with a specialization:

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_;
    }
};

Edit: although I'm not entirely sure what this adds. Wouldn't it be easier to have

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

and use const Interface where appropriate? Or is this not an option for some other reason?

Edit 2: my std::enable_if use was wrong, it's gone now.




回答2:


You can use 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_;
    }
};

Note that the two members need to be made templates and that I'm using a default parameter to force typename std::enable_if<Cond, int>::type to be dependent -- in the scope of the class std::enable_if<isConst, int>::type is not dependent and thus will net a hard-error when the class is instantiated whereas we want SFINAE.

However the default parameter means that someone can do e.g. Interface<true> f; TypeA& ref = f.GetXpo3Container<false>();. If you want to avoid that (e.g. you don't trust users to not misuse unspecified bits of your interface) here's another way to make the member type of std::enable_if dependent again which is perhaps more appropriate, but somewhat more arcane:

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 */



回答3:


You can specialize your template for the case that isConst is true, and make all the member functions const in this case, whilst leaving them non-const in the primary template.

Alternatively, write two versions of the member functions (one const and one not), and use enable_if to only have the appropriate overload enabled.



来源:https://stackoverflow.com/questions/10110082/adding-a-const-qualifier-to-a-member-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!