如何使用Variadic函数与字符串,而不使用模板?

时间:2017-09-01 19:16:39

标签: c++ variadic-functions

我有以下模板功能:

struct ms {
    template <typename... Args>
    void update(string& query, Args&... args);
};

template <typename... Args>
void ms::update(string& query, Args&... args)
{
    const int size = sizeof...(args);
    vector<string> vec = { args... };
    for (int i = 0; i < size; ++i) {
        cout << query << ": " << vec[i] << endl;
    }
}

但是,我想消除模板的使用,只需使其成为一个带有一个或多个字符串参数的成员函数。关于Variadic函数的所有文档和示例我都可以找到使用字符数组并执行while指针!= null来获取数组中的每个值。

如果我这样做:

void update(string& query, string&... args);

如果有任何参数,我将如何迭代args参数?

1 个答案:

答案 0 :(得分:1)

这是array_view<T>

template<class T>
struct array_view;
template<class D>
struct array_view_base;

template<class T>
struct array_view_base<array_view<T>> {
  T* b=0; T* e=0;
  T* begin() const { return b; }
  T* end() const { return e; }
  T& operator[](std::size_t i)const{ return begin()[i]; }
  std::size_t size() const { return end()-begin(); }
  T& front() const { return *begin(); }
  T& back() const { return *(end()-1); }
  array_view<T> without_front( std::size_t N=1 ) const {
    N=(std::min)(N, size());
    return {begin()+N, end()};
  }
  array_view<T> without_back( std::size_t N=1 ) const {
    N=(std::min)(N, size());
    return {begin(), end()-N};
  }

  array_view_base( T* s, T* f ):b(s),e(f){}
  array_view_base( T* s, std::size_t sz ):array_view_base(s, s+sz) {}

  template<std::size_t N>
  array_view_base( T(&arr)[N] ):array_view_base(arr, N) {}
  template<class C,
    std::enable_if_t<!std::is_same<std::decay_t<C>, array_view<T>>{}, int> =0
  >
  array_view_base( C&& c ):array_view_base(c.data(), c.size()) {}
};

template<class T>
struct array_view:array_view_base<array_view<T>> {
  using array_view_base<array_view<T>>::array_view_base;
};
template<class T>
struct array_view<T const>:array_view_base<array_view<T const>> {
  using array_view_base<array_view<T const>>::array_view_base;
  array_view( std::initializer_list<T> il ):array_view( std::addressof(*il.begin()), il.size() ) {}
};

它有点像gsl::span<T>。它是T的连续范围。

gsl::span<T>不同,array_view<T const>可以从initializer_list<T>构建。

使用它,您的代码应如下所示:

struct ms {
  void update(string const& query, array_view<string const> args);
};
void ms::update(string const& query, array_view<string const> args)
{
  for (int i = 0; i < args.size(); ++i) {
    cout << query << ": " << args[i] << endl;
  }
}

你称之为:

ms{}.update( "Hello", {"one", "two", "three"} );

Live example

更糟糕的是,只需选择std::vector<std::string>

通话时

ms{}.update( "Hello", {"one", "two", "three"} );

也有效。与我的解决方案不同,这会导致内存分配。