gpt4 book ai didi

c++ - 如何编写适用于任何类型集合对象的 size() 函数?

转载 作者:IT老高 更新时间:2023-10-28 22:23:24 33 4
gpt4 key购买 nike

我需要一种简单的方法来获取 T 类对象的计数/长度/大小在哪里 T是某种集合类型,例如 std::map , std::list , std::vector , CStringArray , CString , std::string ,……

对于大多数标准类型,T::size()是正确答案,对于大多数 MFC 类 T::GetSize()是正确的,对于 CString , 是 T::GetLength() .

我想点个赞:

template <typename T> auto size(const T & t)

...计算出正确的成员函数调用。

似乎应该有一种简单的方法来调用 T 上的特征模板其中有一个 size(const T & t)成员,它本身使用 SFINAE 存在或不存在,如果存在,则根据定义调用适当的 t.size_function()返回 T 的该实例中的元素计数.

我可以写一个详细的has_member type-trait 模板 - 在 stackoverflow 上有一些示例 - 对于我看来“必须有更简单的方法”,所有这些示例都非常复杂。使用 C++ 17,这个问题似乎应该可以轻松优雅地解决?

这些讨论 herehere似乎使用了一个不优雅的解决方案,其中一些答案使用预处理器宏来完成工作。这还有必要吗?

但是...当然,必须有一种方法可以使用在 T 上调用正确的成员函数这一事实。是可编译的,调用错误的无法编译 - 不能直接为给定类型创建正确的类型特征包装器T ?


我想要一些类似的东西:

template <typename T>
auto size(const T & collection)
{
return collection_traits<T>::count(collection);
}

collection_traits<T> 的确切特化在哪里被选中是因为它是唯一适合 T 的(即它调用正确的实例方法)。

最佳答案

您可以使用 expression SFINAE和多个重载。

思路如下:检查x.size()是您的类型的有效表达式 - 如果是,则调用并返回它。重复 .getSize.getLength .

给定:

struct A { int size() const { return 42; } };
struct B { int getSize() const { return 42; } };
struct C { int GetLength() const { return 42; } };

您可以提供:

template <typename T>
auto size(const T& x) -> decltype(x.size()) { return x.size(); }

template <typename T>
auto size(const T& x) -> decltype(x.getSize()) { return x.getSize(); }

template <typename T>
auto size(const T& x) -> decltype(x.GetLength()) { return x.GetLength(); }

用法:

int main()
{
size(A{});
size(B{});
size(C{});
}

live example on wandbox.org

此解决方案易于扩展,并可与模板化容器无缝协作。


What if a type exposes two getters?

上述解决方案会导致歧义,但通过引入解决该问题的排名/排序很容易解决。

首先,我们可以创建一个 rank允许我们任意确定重载优先级的类:

template <int N> struct rank : rank<N - 1> { };
template <> struct rank<0> { };

rank<N>可隐式转换为 rank<N - 1> .在重载解析期间,完全匹配比一连串的转换要好。

然后我们可以创建 size_impl 的层次结构重载:

template <typename T>
auto size_impl(const T& x, rank<2>)
-> decltype(x.size()) { return x.size(); }

template <typename T>
auto size_impl(const T& x, rank<1>)
-> decltype(x.getSize()) { return x.getSize(); }

template <typename T>
auto size_impl(const T& x, rank<0>)
-> decltype(x.GetLength()) { return x.GetLength(); }

最后我们提供一个接口(interface)函数,开始向右调度size_impl过载:

template <typename T>
auto size(const T& x) -> decltype(size_impl(x, rank<2>{}))
{
return size_impl(x, rank<2>{});
}

使用像 D 这样的类型下面

struct D
{
int size() const { return 42; }
int getSize() const { return 42; }
int GetLength() const { return 42; }
};

现在将选择 rank<2> size_impl 的过载:

live example on wandbox

关于c++ - 如何编写适用于任何类型集合对象的 size() 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48648148/

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