我目前正在编写一个接口类,它应该提供对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>
配置。
答案 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 */