有没有一种通用的方法可以从C++容器中获取`size_type`?

4

是否可以从容器(如std::vectorstd::map)中获取size_type的类型别名,而不需要提供某种value_type

我正在编写一个程序,需要使用两种不同的map类型的size_type。然而,如果我为第一个map类型创建一个typedef,那么第二个map类型将无法使用size_type这个名称。我的解决方法(也就是“临时应急方案”)是撒谎。

std::map<char, int> letters;
std::map<std::string, int> digraphs, trigraphs;

// This lie is good enough for both map types.
using size_type = typename std::map<int, int>::size_type;

在其他情况下,我宁愿不提供一个"value_type"。这里有一个人为的例子。
// Yes, I know this can be cleaned up by doing it in stages, but ugh!
using size_type = typename std::map<std::string, std::pair<std::string, std::string>>::size_type;

说到底,我们都知道size_type很可能会成为std::size_t的别名,即使在像std::vector<bool>这样的特殊情况下也是如此。尽管如此,我仍然试图以“正确”的方式来做事,使用size_type

那么,有没有办法在不提供value_type的情况下获取size_type呢?


6
不,不可能的。而且如果你追求完全正确,你能确定不同的实例会有相同的size_type吗? - HolyBlackCat
4
是的,我从来都不喜欢size_type。它太啰嗦了,而且很少见到代码一致使用它。我是那些通常在任何地方使用size_t的异类之一。也许我是问题的一部分。 - paddy
1
我同意在所有地方使用std::size_t是足够正确的。 - HolyBlackCat
2
只需使用std::size_t。无论如何,它始终是std::size_t。关于它可能有所不同的理论讨论并不实用。 - Aykhan Hagverdili
1
@Nelfeal:是的,我基本上得出结论,在原始问题中给定的特定用例中,我将添加static_assert(std::is_same_v<std::size_t, decltype(letters)::size_type>);,对于digraphs等也会类似进行断言,然后在此之后使用std::size_t。这样我就不必撒谎了! - tbxfreeware
显示剩余12条评论
2个回答

6
所以,有没有一种方法可以在不提供value_type的情况下获得size_type? 没有,因为对于每个value_type,size_type可以是不同的类型。 当然,正如你自己所说的,通常情况下,size_type几乎总是std::size_t,但标准库实现本身以及容器模板的用户定义的特化都允许为不同的value_type不同地定义size_type,并且没有要求它必须与std::size_t相关联。 甚至没有任何要求size_type必须比std::size_t小或大。如果你想要具有适用于任何符合标准的实现的通用库代码,你将必须始终单独考虑size_type并且不对它们之间的关系做任何假设。

2
感谢所有的帮助。
我已经给@user17732522提供的答案点赞,并将其标记为采纳的答案。
此外,@Nelfeal在原始问题中给出了最佳答案。我不应该创建自己的size_type类型定义,而应该使用std::size_t,如果我担心容器可能使用其他类型,可以在using语句之前添加static_asserts
std::map<char, int> letters;
std::map<std::string, int> digraphs, trigraphs;

static_assert(std::is_same_v<std::size_t, std::map<char, int>::size_type>);
static_assert(std::is_same_v<std::size_t, std::map<std::string, int>::size_type>);

// From here forward, std::size_t is guaranteed to be the correct size.
// I can use it directly, or optionally, create a type alias that is not a lie.
using size_type = std::size_t;

你也可以看一下https://dev59.com/M1oV5IYBdhLWcg3wa-Qo以及相关内容。也许你可以“选择”最适合所有情况的类型。 - Swift - Friday Pie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接