无法推断出' auto'来自' tuple_cat'

时间:2017-06-22 22:21:17

标签: c++ variadic-templates optional template-specialization c++17

基本问题

我试图解决的基本问题是:

我有一个模板参数包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 } } } 编译)

感谢您的时间和/或帮助!

2 个答案:

答案 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>...>();
    }
};