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::array
和 std::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"});
但是,如您所见,这对您来说可能过于冗长了。但是,您可以通过定义一个接受 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});
我一直在尝试编写一些仍然使用 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::array
和 std::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"});
但是,如您所见,这对您来说可能过于冗长了。但是,您可以通过定义一个接受 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});