shorthand std::array 文字参数

shorthand std::array literal parameter

我一直在尝试编写一些仍然使用 std::array 的较短代码,但我不确定如何让推导对我有利。

有没有一种方法可以像矢量版本一样简短(可读)?

#include <array>
#include <iostream>
#include <vector>

template <std::size_t SIZE>
void afunc(const std::array<std::string_view, SIZE> &v)
{
    for(int i=0; i<10; i++)
    {
        std::cout << v[rand()%SIZE];
    }
}

void vfunc(const std::vector<std::string_view> &v)
{
    for(int i=0; i<10; i++)
    {
        std::cout << v[rand()%v.size()];
    }
}

using namespace std::string_view_literals;

int main()
{
  std::array<std::string_view, 2> works = {"1","2"};
  afunc(works);// verbose
  //afunc({ "1","2" }); // 1st  fail
  //afunc({ "1"sv,"2"sv }); // 2nd fail
  //afunc(std::array{ "3","4" });// 3rd fail
  afunc(std::array{ "3"sv,"4"sv, "test"sv,"other"sv });// works but verbose

  vfunc({"5","6", "7"});// vectors are easy to code with

  return 0;
}

您无法从初始化列表参数推断编译时大小,因此您需要显式传递大小:

template <std::size_t Size>
void afunc(const std::array<std::string_view, Size> &v)
{ ... }

int main()
{
    afunc<2>({ "1", "2" }); // ok
}

您的 vfunc for std::vector 不需要推断编译时大小,这就是为什么此限制仅适用于 std::array in [=14] 的模板参数推导=].

了解如何让 C 样式数组作为一个选项工作。当我在我的引用不是 const 之前尝试过这个时,因此不会用临时编译。由于缺少迭代器,不如数组好,但仍然简单

template<size_t N> 
 void carr_try(std::string_view const(&a)[N])
 { 
    for(int i=0; i<10; i++)
    {
        std::cout << a[rand()%N];
    }
 }

// for illustrative purposes of how to NOT write this routine
 template<size_t N> 
 void nonconst(std::string_view (&a)[N]) 
 { 
    for(int i=0; i<10; i++)
    {
        std::cout << a[rand()%N];
    }
 }


int main()
{
    carr_try({ "1", "2" }); // ok
//nonconst({"1","2"});// not ok
std::string_view temp[]={"3","4"};
nonconst(temp);// is fine but long
}

std::arraystd::vector 具有相同的 size()operator[] 成员,因此您可以将 2 个函数合并为 1 个函数:

template <typename Container>
void func(const Container &c)
{
    for(int i = 0; i < 10; ++i)
    {
        std::cout << c[rand() % c.size()];
    }
}
std::array<std::string_view, 2> a{"1","2"};
func(a);

std::vector<std::string_view> v{"1","2"};
func(v);

func<std::array<std::string_view, 2>>({"1","2"});

func<std::vector<std::string_view>>({"1","2"});

Demo

但是,如您所见,这对您来说可能过于冗长了。但是,您可以通过定义一个接受 std::initializer_list 作为参数的额外函数来支持括号列表作为参数 而无需 显式指定模板参数,然后编译器可以为您推断出该参数。

但是,std::initializer_list 没有 operator[],因此如果您打算在函数之间共享公共代码,则必须更改主函数逻辑以使用随机访问迭代器,例如:

template <typename Iter>
void func(Iter begin, Iter end, std::random_access_iterator_tag)
{
    size_t size = end - begin;
    for(int i = 0; i < 10; ++i)
    {
        std::cout << *(begin + (std::rand() % size));
    }
}

template <typename Iter>
void func(Iter begin, Iter end)
{
    func(begin, end,
      typename std::iterator_traits<Iter>::iterator_category());
}

template <typename Container>
void func(const Container &c)
{
    func(std::begin(c), std::end(c));
}

template <typename T>
void func(const std::initializer_list<T> &l)
{
    func(l.begin(), l.end());
}
std::array<std::string_view, 2> a{"1","2"};
func(a);

std::vector<std::string_view> v{"1","2"};
func(v);

func({"1"sv, "2"sv});

Demo