将const限定符添加到成员函数

时间:2012-04-11 16:30:48

标签: c++ templates c++11 template-meta-programming typetraits

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

我已经使用'type_traits''std :: add_const'来有条件地限定内部成员函数的返回类型,遗憾的是我无法想到一种有条件地将成员函数定义为const或非const的方法。

这甚至可能吗?如果是这样的话?

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

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

3 个答案:

答案 0 :(得分:5)

这对于专业化来说似乎最容易做到:

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使用错误,现在已经消失了。

答案 1 :(得分:1)

您可以针对isConst为真的情况对您的模板进行专门化,并在这种情况下制作所有成员函数const,同时在主模板中保留非const

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

答案 2 :(得分:1)

您可以使用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>();。如果你想避免这种情况(例如你不相信用户不滥用你的界面的未指定位),这是使type成员std::enable_if再次依赖的另一种方式,这可能更合适,但是有点神秘:

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