如何确保传递给可变参数模板函数的所有容器都具有相同的大小?

时间:2012-07-18 21:36:23

标签: c++ c++11 variadic-templates

示例

#include <vector>
#include <cassert>

template <typename Cont, typename... Rest>
void f(Cont& c, Rest&... rest)
{
    assert(c.size() == ???);
}


int main()
{
    std::vector<int> v1(10);
    std::vector<int> v2(10);
    std::vector<int> v3(10);
    std::vector<int> v4(10);

    f(v1, v2, v3, v4);
}

我想确保传递给函数的所有容器大小相同。但是,该函数是一个可变参数模板,它采用相同类型的任意数量的容器。这可能吗?

4 个答案:

答案 0 :(得分:7)

#include <vector>
#include <cassert>

template <typename Size>
bool check_size(Size) {
  return true;
}

template <typename Size, typename Cont, typename... Rest>
bool check_size(Size expected, Cont& c, Rest&... rest) {
  return (c.size() == expected && check_size(expected, rest...));
}

template <typename Cont, typename... Rest>
void f(Cont& c, Rest&... rest)
{
  assert(check_size(c.size(), rest...));
}

int main()
{
    std::vector<int> v1(10);
    std::vector<int> v2(10);
    std::vector<int> v3(10);
    std::vector<int> v4(10);

    f(v1, v2, v3, v4);
}

答案 1 :(得分:0)

标准范例是“先休息”模板。所以你要声明一个验证模板函数,它接受第一个参数(一个带有size()成员的容器)和一个“rest”参数(可变参数部分),并返回有效的休息列表中的元素个数或一个数字在错误之外设置(例如-1)。一个单独的validate()模板只需要一个参数,并且如果rest具有单个元素,则选择该参数;它只会返回元素的大小。

但是......哎呀。这里的目标是什么?

答案 2 :(得分:0)

这样的事情应该做(我没有检查,手头没有编译器)

template <typename Cont, typename... Rest>
void assertAllOfSize(int size, Cont& first, Rest&... rest)
{
    assert(first.size() == size);
    assertAllOfSize(size, rest...);
}

template <typename Cont, typename... Rest>
void assertAllEqualSize(Cont& first, Rest&... rest)
{
    assertAllOfSize(first.size(), rest...);
}

template <typename Cont> // terminate recursion
void assertAllOfSize(int size, Cont& first)
{
    assert(first.size() == size);
}

答案 3 :(得分:0)

您可以使用“通常”模式,但有两个命名参数:

template <typename ...Args> bool AllTheSame(Args &&...) { return true; }

template <typename A, typename B, typename ...Rest>
bool AllTheSame(A && a, B && b, Rest &&... rest)
{
    return a.size() == b.size() &&
           AllTheSame(std::forward<B>(b), std::forward<Rest>(rest)...);
}