如何判断某件事是否是一个容器?

时间:2016-06-10 00:35:46

标签: c++ templates iterator containers sfinae

我想确定某件事是否是一个容器。现在我正在对格式化为具有类型和分配器的容器进行测试。我的最终目标是学习如何编写容器模板,当包含自身层时,可以允许直接迭代其最内层元素。例如。如果有一个容器包含3个容器,每个容器包含3个容器,每个容器包含3个元素,我希望能够基于循环遍历一个范围内的所有27个元素。区分某个东西是直接包含元素的容器还是包含元素容器(或容器的容器容器......元素的容器),使用SFINAE来检查元素是否具有迭代器,这似乎是确定{{{ 1}}函数应该将迭代器返回到元素或所述元素的begin()函数的结果。如果我可以迈出第一步,我想把这个逻辑包含在编写我的容器中,但是我无法编译它:

begin()

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:5)

您对某个容器是否是容器的定义似乎完全取决于它是否具有iterator内部类。

我认为,这与任何启发式一样好,但我们可以选择。

在大多数情况下,如果使用类完成SFINAE更简单,而不是尝试使用函数实现SFINAE,例如is_container()。将is_container()放入课程会产生以下教科书SFINAE解决方案:

#include <vector>
#include <string>
#include <iostream>
#include <type_traits>

template<typename ...>
using void_t=void;

template<typename T, class=void> struct is_container : std::false_type {};

template<typename T>
struct is_container<T, void_t<typename T::iterator>> : std::true_type {};

int main()
{
    std::cout << is_container<int>::value << std::endl;

    std::cout << is_container<std::vector<int>>::value << std::endl;
    return 0;
}

现在,一个相关的问题是,是否有更好的方法来检查某件事是否是一个容器。无论您选择哪种启发式方法,调整基于类的测试都是微不足道的,而不是基于函数的测试。例如,如果您想要考虑某个容器是否是容器,如果它同时具有iteratorconst_iterator内部类,则只需要更改一行:

template<typename T>
struct is_container<T, void_t<typename T::iterator,
                              typename T::const_iterator>> : std::true_type {};