5

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

我已经使用 'type_traits' 'std::add_const' 有条件地限定内部成员函数的返回类型,不幸的是我想不出有条件地将成员函数限定为 const 或非 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
};

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

4

3 回答 3

6

这似乎最容易通过专业化来完成:

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

于 2012-04-11T16:40:38.643 回答
2

您可以使用 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_ifdependent,这可能更合适,但更神秘:

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 */
于 2012-04-11T16:50:45.000 回答
1

您可以针对正确的情况专门化您的模板isConst,并在这种情况下制作所有成员函数const,同时将它们留在非const主模板中。

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

于 2012-04-11T16:41:18.117 回答