如何传递临时数组?我想做这样的事情:
#include <iostream>
int sum(int arr[]) {
int answer = 0;
for (const auto& i : arr) {
answer += i;
}
return answer;
}
int main() {
std::cout << sum( {4, 2} ) << std::endl; // error
std::cout << sum( int[]{4, 2} ) << std::endl; // error
}
我是否需要在函数参数&#39;大括号[]
中使用正整数文字?如果我包含该文字,它会限制我可以传递给那个大小的数组的数组吗?另外,如何通过rvalue引用或const引用传递数组元素?由于上面的示例没有编译,我认为函数的参数类型int&&[]
或const int&[]
不会起作用。
答案 0 :(得分:11)
首先,您不能传递数组作为prvalues,因此您的函数需要参考。其次,数组的大小是类型的一部分,因此您的函数可能需要成为模板的一部分。第三,编写数组临时工具在词汇上有点傻,所以你需要一些噪音。
总而言之,以下应该有效
template <std::size_t N>
int sum(const int (&a)[N])
{
int n = 0;
for (int i : a) n += i;
return n;
}
int main()
{
using X = int[3];
std::cout << sum(X{1, 2, 3}) << "\n";
}
语法噪音可以使用别名模板略微推广:
template <std::size_t N> using X = int[N];
用法:sum(X<4>{1, 2, 3, 4})
(您无法从初始化程序中推断出模板参数。)
答案 1 :(得分:1)
我建议将sum函数设置为接受任何范围的模板,而不是将其限制为数组。这样你就可以使用标准容器的函数,比如std :: vector,std :: set甚至是用户定义的容器。
我的解决方案需要boost.range库,但今天谁还没有使用boost?范围甚至被认为是添加到标准库中。
#include <iostream>
#include <array>
#include <vector>
#include <string>
#include <boost/range.hpp>
#include <initializer_list>
template< typename Range >
auto sum_impl( const Range& range ) -> typename boost::range_value< Range >::type
{
typename boost::range_value< Range >::type result{};
for( const auto& elem : range )
result += elem;
return result;
}
template< typename Range >
auto sum( const Range& range ) -> typename boost::range_value< Range >::type
{
return sum_impl( range );
}
template< typename Elem >
Elem sum( const std::initializer_list< Elem >& range )
{
return sum_impl( range );
}
int main()
{
// Call the initializer_list overload
std::cout << sum( { 1, 2, 3 } ) << "\n";
std::cout << sum( { 1.0f, 2.1f, 3.2f } ) << "\n";
// Call the generic range overload
std::cout << sum( std::array<int,3>{ 1, 2, 3 } ) << "\n";
std::cout << sum( std::vector<float>{ 1.0f, 2.1f, 3.2f } ) << "\n";
std::cout << sum( std::vector<std::string>{ "a", "b", "c" } ) << "\n";
}
一些解释:
我使用auto
作为返回类型只是为了使函数声明更具可读性。你也可以这样写:
typename boost::range_value< Range >::type sum( const Range& range )
boost::range_value
模板用于推断范围元素的类型。这样我们就可以将sum()不仅用于整数,而且还可以使用operator +=
定义的任何东西!您可以在我的示例中看到我们甚至可以添加&#34; (连接)字符串在一起。 :d
最后使用std::initializer_list
参数的重载使得简单的语法成为可能,我们可以根据OP的请求调用sum({ 1, 2, 3 })
。此重载是必需的,因为泛型重载不会推断出initializer_list参数类型(另请参阅initializer_list and template type deduction)
<强>演示:强>