gpt4 book ai didi

c++ - 有条件地启用一个子类型(类似于enable_if来启用功能)

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:31:46 25 4
gpt4 key购买 nike

我有一个特征类,它通过推导成员函数的类型来定义“范围”(或容器、序列)的类型,如下所示:

template<class R>
struct range_type_traits
{
// "iterator": The type of the iterators of a range
using iterator = decltype(std::begin(std::declval<R>()));

// "value_type": The (non-reference) type of the values of a range
using value_type = typename std::remove_reference<decltype(*(std::declval<iterator>()))>::type;
};

我这样做的原因(而不是直接使用 R 的子类型或 std::iterator_traits )是为了支持某些具有 begin() 的模板库中的任何类型的容器。成员并且不需要容器有一些 value_type/iterator定义的类型。据我所知,std::iterator_traits对于不使用成对将其迭代器接口(interface)公开给 STL 的容器,无法处理某种“键类型”,例如 std::map确实(例如:QMap<K,T>value_type = T 。您可以通过 iterator::key() 访问 key )。

现在我想有条件地定义一个类型 key_type iif iterator有一个函数 ::key() const并采用它的返回类型,类似于我对 value_type 所做的.如果我只是将定义放在现有的特征类中,对于不支持它的容器,编译将失败。

SFINAE std::enable_if可以有条件地启用模板函数。如何有条件地扩展现有类/有条件地定义子类型?

像这样的草图:

template<class R>
struct range_type_traits
{
// "iterator": The type of the iterators of a range
using iterator = decltype(std::begin(std::declval<R>()));

// "value_type": The (non-reference) type of the values of a range
using value_type = typename std::remove_reference<decltype(*(std::declval<iterator>()))>::type;

ENABLE_IF_COMPILATION_DOES_NOT_FAIL {
// "key_type": The (non-reference) type of the keys of an associative range not using pairs in its STL-interface
using key_type = typename std::remove_reference<decltype(std::declval<iterator>().key())>::type;
}
};

最佳答案

您可以在类模板上使用 SFINAE 创建一个基类模板,当且仅当满足您需要的条件时,该模板定义 key_type:

namespace detail
{

// Primary template (does not define key_type)
template<typename R, typename = void>
struct key_type_definer { };

// Specialization using SFINAE to check for the existence of key() const
// (does define key_type)
template<typename R>
struct key_type_definer<
R,
typename std::enable_if<
std::is_same<
decltype(std::declval<R const>().key()),
decltype(std::declval<R const>().key())
>::value
>::type
>
{
// Type alias definition
using key_type = typename std::remove_reference<
decltype(std::declval<R const>().key())
>::type;
};

} // end namespace detail

然后,您可以从 key_type_definer 类模板中派生出您的 range_traits 类模板,方法如下:

template<class R>
struct range_type_traits : detail::key_type_definer<R>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
// ...
};

range_type_traits 现在将定义一个名为 key_type 的类型别名当且仅当 R 有一个成员函数 R key() const ,其中 R 将是 key_type 别名的类型。

关于c++ - 有条件地启用一个子类型(类似于enable_if来启用功能),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15999441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com