sfinae 检测容器:std:array 失败

keb*_*ebs 6 c++ templates sfinae variadic-templates stdarray

我正在寻找一种使用 SFINAE 来实现某些功能的方法,该功能必须仅适用于某些容器:向量、列表、数组(设置在下面仅作为测试)

基于这个答案,我尝试了下面的代码,该代码使用了一个仅对所需容器返回 true 的特性类。

正如您在此处在线看到的,它失败了std::array

template <typename Container>
struct is_container : std::false_type { };

template <typename... Ts> struct is_container<std::array<Ts... >> : std::true_type { };
template <typename... Ts> struct is_container<std::vector<Ts...>> : std::true_type { };
template <typename... Ts> struct is_container<std::set<Ts...   >> : std::true_type { };
template <typename... Ts> struct is_container<std::list<Ts...  >> : std::true_type { };
template <typename... Ts> struct Dummy{};

int main()
{
    std::cout << "Dummy: " << is_container<Dummy<int>>::value << '\n';
    std::cout << "array: " << is_container<std::array<int,5>>::value << '\n';
    std::cout << "vector:" << is_container<std::vector<int>>::value << '\n';
    std::cout << "set: "   << is_container<std::set<int>>::value << '\n';
    std::cout << "list: "  << is_container<std::list<int>>::value << '\n';
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,这是因为std::array需要第二个模板参数。我对可变参数模板的经验不足,所以我的问题是:

有没有办法使这种方法成功? 或者我应该使用链接问题中描述的另一种方法吗?

我宁愿有一些纯 C++11,但 C++14 也可以。

bit*_*ask 7

这不是 SFINAE 而是常规模板专业化。您的 std::array 无法识别,因为 std::size_t 类型的值(它是 std::array 的第二个参数)不是类型名。

您可以专门更改对数组的检查:

template <typename T, std::size_t N> struct is_container<std::array<T,N>> : std::true_type { };
template <typename... Ts> struct is_container<std::vector<Ts...>> : std::true_type { };
Run Code Online (Sandbox Code Playgroud)

如果您真的想使用SFINAE来检查任何行为类似于容器的东西,您可以检查该类型是否存在 std::begin、std::end、std::size。


son*_*yao 5

问题是第二个模板参数std::array是一个非类型模板参数,它与类型模板参数包不匹配typename... Ts

您可以将专业化更改为std::array

template <typename T, std::size_t S> struct is_container<std::array<T, S>> : std::true_type { };
Run Code Online (Sandbox Code Playgroud)