在python中,我们可以这样做:
int_list = [1, 2, 3, 4, 5]
print(sum(int_list)) # prints 15
float_tuple = (1.2, 3.4, 9.9)
print(sum(float_tuple)) # prints 14.5
sum
函数接受任何可迭代的元素,这些元素知道如何相互添加到0并产生总和。
我想在C ++ 11中创建一个相同的函数。我知道存在accumulate
方法,但我想要一个带有单个参数的函数。基本上,我想知道如何编译以下代码:
#include <string>
#include <iostream>
#include <vector>
#include <deque>
#include <list>
template<typename iterable>
auto sum(iterable iterable_) {
auto it = iterable_.begin();
auto end = iterable_.end();
if (it == end) {
return 0;
}
auto res = *(it++);
while (it != end) {
res += *it++;
}
return res;
}
int main() {
std::vector<int> int_vector = {0, 1, 2, 3, 4, 5};
std::cout << sum(int_vector) << '\n'; // prints 15
std::deque<int> int_deque = {4, 5, 7};
std::cout << sum(int_deque) << '\n'; // prints 16
std::list<float> float_list = {1.2, 3.4, 9.9};
std::cout << sum(float_list) << '\n'; // should print 14.5, but produces error.
}
此代码几乎有效。问题是auto
在iterable为空的情况下看到return 0;
,并且假定函数必须返回int
。然后它看到float
版本返回float
并且它会混淆。有没有办法告诉编译器,如果return float(0)
后来发现return
返回float
,请说@interface AppDelegate () <UITabBarControllerDelegate>
@property (nonatomic, strong) PDFDocumentStore *documentStore;
@property (nonatomic, strong) DocumentListViewController *documentsViewController;
@property (nonatomic, strong) DocumentListViewController *recentViewController;
@property (nonatomic, assign) BOOL launchingWithURL;
@property (nonatomic, assign) BOOL addSkipBackupAttributeToItemAtURL;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self migrateIfNeeded];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil];
UIViewController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"Login"];
[[UIApplication sharedApplication].keyWindow setRootViewController:rootViewController];
self.documentStore = PDFDocumentStore.new;
[self.documentStore.rootFolder load];
UITabBarController *tabBar = (UITabBarController *)[[self window] rootViewController];
tabBar.delegate = self;
self.documentsViewController = (DocumentListViewController *)[tabBar.viewControllers[0] topViewController];
FolderDocumentListViewModel *folderModel =
[[FolderDocumentListViewModel alloc] initWithFolder:self.documentStore.rootFolder];
self.documentsViewController.viewModel = folderModel;
[self.documentsViewController view];
self.recentViewController = (DocumentListViewController *)[tabBar.viewControllers[1] topViewController];
RecentDocumentListViewModel *recentModel =
[[RecentDocumentListViewModel alloc] initWithDocumentList:self.documentStore.documentList];
self.recentViewController.viewModel = recentModel;
NSString *pdf = @"2016 Product Handbook";
NSString *toPath = [[[NSFileManager grt_documentsPath]
stringByAppendingPathComponent:pdf]
stringByAppendingPathExtension:@"pdf"];
[self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:toPath]];
NSURL *URL = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
if (URL) {
self.launchingWithURL = YES;
}
return YES;
}
?
答案 0 :(得分:5)
是的,你可以至少为标准容器做这项工作。
标准容器为存储在该容器中的值类型定义名为value_type
的类型别名。对于空容器,您可以返回此类型的值构造对象:
template<typename iterable>
auto sum(iterable const &iterable_) {
auto it = iterable_.begin();
auto end = iterable_.end();
if (it == end) {
return typename iterable::value_type();
}
auto res = *(it++);
while (it != end) {
res += *it++;
}
return res;
}
这取决于所包含的类型是默认构造的,但这可能不是一个主要问题(当然适用于int
和float
等原始类型。
答案 1 :(得分:5)
如果您想要使用任何 C ++ 11范围(即,您可以在基于范围的表达式中迭代的任何内容 - 包括数组以及具有免费的容器) begin
和end
),我们可以添加一些使用声明并换行std::accumulate
template <class Range>
auto sum(Range&& range) {
using std::begin;
using std::end;
using T = std::decay_t<decltype(*begin(range))>;
return std::accumulate(begin(range), end(range), T{});
}
如果您不想包装accumulate
,那么您也可以重新实现该循环以执行相同的操作。
答案 2 :(得分:2)
以下方法即使对非标准容器也适用;只要某些内容以合理的方式实现channel
和begin()
。
end()