我试图解决的基本问题是:
我有一个模板参数包ArgTypes,我需要用std :: optional中包含的每个类型创建一个元组。例如:std::tuple<std::optional<int>, std::optional<double>, std::optional<std::string>>
应返回类型std::nullopt
的元组元组,元组中的每个元素都初始化为g++
。
我使用GCC 7.1附带的error: unable to deduce 'auto' from 'tuple_cat<std::make_tuple(_Elements&& ...) [with _Elements = {std::optional<int>&}](), optional_tuple>'
。我已经和C ++类型系统搏斗了很长一段时间,而且我的代码适用于一种类型而不是多种类型。我在参数包中遇到多种类型的错误是:
auto optional_tuple
有谁知道如何解决这个问题?直觉(虽然我可能不正确)我认为问题是C ++类型系统无法推断出auto
的类型,因为它涉及完全解析参数包产生的不同函数模板的递归链 - - 当尝试解析#include <optional>
#include <tuple>
template<int n, typename ArgType, typename... ArgTypes>
struct make_optional_tuple_helper {
static auto tuple() {
std::optional<ArgType> optional_arg = {};
auto optional_tuple = make_optional_tuple_helper<n-1, ArgTypes...>::tuple();
return std::tuple_cat<std::make_tuple(optional_arg), optional_tuple>;
}
};
template<typename ArgType>
struct make_optional_tuple_helper<1, ArgType> {
static std::tuple<std::optional<ArgType>> tuple() {
std::optional<ArgType> optional_arg = {};
return std::make_tuple(optional_arg);
}
};
template<typename... ArgTypes>
auto make_optional_tuple() {
return make_optional_tuple_helper<std::tuple_size<std::tuple<ArgTypes...>>::value, ArgTypes...>::tuple();
};
int main() {
auto i = make_optional_tuple<int>(); // works!
auto j = make_optional_tuple<int, double>(); // error: unable to deduce 'auto'...
}
变量的类型时类型系统可能无法执行的操作。
这是一个最小的工作示例:
g++-7 -std=c++1z example.cpp
(与import UIKit
import Firebase
import FirebaseDatabase
import SDWebImage
struct postStruct {
let title : String!
let author : String!
let date : String!
let article : String!
let downloadURL : String!
}
class ZeroHomeViewController: UITableViewController {
var posts = [postStruct]()
var downloadURL : String = ""
override func viewDidLoad() {
super.viewDidLoad()
let ref = Database.database().reference().child("Posts")
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount)
for rest in snapshot.children.allObjects as! [DataSnapshot] {
guard let value = rest.value as? Dictionary<String,Any> else { continue }
guard let title = value["Title"] as? String else { continue }
guard let downloadURL = value["Download URL"] as? String else { continue }
guard let author = value["Author"] as? String else { continue }
guard let date = value["Date"] as? String else { continue }
guard let article = value["Article"] as? String else { continue }
let post = postStruct(title: title, author: author, date: date, article: article, downloadURL: downloadURL)
self.posts.append(post)
}
self.posts = self.posts.reversed(); self.tableView.reloadData()
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let label1 = cell?.viewWithTag(1) as! UILabel
label1.text = posts[indexPath.row].title
let imageView = cell?.viewWithTag(2) as! UIImageView
let post = self.posts[indexPath.row];
imageView.sd_setImage(with: URL(string: post.downloadURL), placeholderImage: UIImage(named: "placeholder"))
return cell!
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "detail" {
if let indexPath = tableView.indexPathForSelectedRow {
let destVC = segue.destination as! ArticleViewController
destVC.titleText = value["Title"] as? String
}
}
}
编译)
感谢您的时间和/或帮助!
答案 0 :(得分:3)
你方式过度思考:
template<typename... ArgTypes>
auto make_optional_tuple() {
return std::tuple<std::optional<ArgTypes>...>{};
}
由于默认构造的可选项是nullopt,这就是你所需要的。
您的特定问题是您使用了错误的括号:
return std::tuple_cat<std::make_tuple(optional_arg), optional_tuple>;
~~~ ~~~
那些应该是圆括号。按原样,您将返回一个指向格式错误的函数模板特化而不是元组的指针。
答案 1 :(得分:-2)
它不起作用,因为函数的返回类型是在第一次返回时推断出来的,而你试图在第一次返回之前调用该函数。
我相信你可以做很多事情:
template<typename... ArgTypes>
struct make_optional_tuple_helper {
static auto tuple() {
return std::make_tuple(std::optional<ArgTypes>()...);
}
};
或者
template<typename... ArgTypes>
struct make_optional_tuple_helper {
static auto tuple() {
return std::tuple<std::optional<ArgTypes>...>();
}
};