无法从 'tuple_cat' 推导出 'auto'
Unable to deduce 'auto' from 'tuple_cat'
基础问题
我要解决的基本问题是:
我有一个模板参数包 ArgTypes,我需要用包含在 std::optional 中的每个类型创建一个元组。例如:make_optional_tuple<int, double, std::string>
应该 return 类型为 std::tuple<std::optional<int>, std::optional<double>, std::optional<std::string>>
的元组的元组,元组中的每个元素都初始化为 std::nullopt
.
我目前的工作
我正在使用 GCC 7.1 中包含的 g++
。我已经研究 C++ 类型系统很长时间了,我的代码适用于一种类型,但不适用于多种类型。我在参数包中使用多种类型时得到的错误是:
error: unable to deduce 'auto' from 'tuple_cat<std::make_tuple(_Elements&& ...) [with _Elements = {std::optional<int>&}](), optional_tuple>'
有谁知道我该如何解决这个问题?直觉上(尽管我可能不正确)我认为问题在于 C++ 类型系统无法推断 auto optional_tuple
的类型,因为它涉及完全解析由参数包生成的不同函数模板的递归链 - - 类型系统在尝试解析 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
编译)
感谢您的宝贵时间and/or帮助!
它不会工作,因为函数的 return 类型是在第一个 return 上推导的,而您正试图在第一个 return 之前调用该函数。
我相信你可以做一些长线的事情:
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>...>();
}
};
你方式想多了:
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>;
~~~ ~~~
那些应该是括号。按原样,您将返回指向格式错误的函数模板特化而不是元组的指针。
基础问题
我要解决的基本问题是:
我有一个模板参数包 ArgTypes,我需要用包含在 std::optional 中的每个类型创建一个元组。例如:make_optional_tuple<int, double, std::string>
应该 return 类型为 std::tuple<std::optional<int>, std::optional<double>, std::optional<std::string>>
的元组的元组,元组中的每个元素都初始化为 std::nullopt
.
我目前的工作
我正在使用 GCC 7.1 中包含的 g++
。我已经研究 C++ 类型系统很长时间了,我的代码适用于一种类型,但不适用于多种类型。我在参数包中使用多种类型时得到的错误是:
error: unable to deduce 'auto' from 'tuple_cat<std::make_tuple(_Elements&& ...) [with _Elements = {std::optional<int>&}](), optional_tuple>'
有谁知道我该如何解决这个问题?直觉上(尽管我可能不正确)我认为问题在于 C++ 类型系统无法推断 auto optional_tuple
的类型,因为它涉及完全解析由参数包生成的不同函数模板的递归链 - - 类型系统在尝试解析 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
编译)
感谢您的宝贵时间and/or帮助!
它不会工作,因为函数的 return 类型是在第一个 return 上推导的,而您正试图在第一个 return 之前调用该函数。
我相信你可以做一些长线的事情:
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>...>();
}
};
你方式想多了:
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>;
~~~ ~~~
那些应该是括号。按原样,您将返回指向格式错误的函数模板特化而不是元组的指针。