Base Problem
The base problem I'm trying to solve is this:
I have a template parameter pack ArgTypes and I need to make a tuple with each of the types wrapped in std::optional. For example: make_optional_tuple<int, double, std::string>
should return a tuple of tuple of type std::tuple<std::optional<int>, std::optional<double>, std::optional<std::string>>
with each element in the tuple initialized to std::nullopt
.
My work so far
I'm using g++
included with GCC 7.1. I've been wrestling with the C++ type system for quite a while and I have code that works with one type but not multiple types. The error I get with multiple types in the parameter pack is:
error: unable to deduce 'auto' from 'tuple_cat<std::make_tuple(_Elements&& ...) [with _Elements = {std::optional<int>&}](), optional_tuple>'
Does anyone know how I can fix this? Intuitively (though I may be incorrect) I think the problem is that the C++ type system is unable to deduce the type of auto optional_tuple
as it involves fully resolving the chain of recursions of the different function templates produced by the parameter pack -- something that perhaps the type system is unable to do when it is trying to resolve the type of auto
variables.
Here is a minimal working example:
#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'...
}
(Compile with g++-7 -std=c++1z example.cpp
)
Thanks for your time and/or help!