Не уверен, что понимаю ваш код, но ... мне кажется, что проблема в этом разделе (удалены комментарии и немного упрощено)
auto gresult = other(*(args)...);
if (gresult)
return this->eval_(gresult);
Какой тип gresult
?
Я полагаю, вы ожидаете, что это std::optional
определенного типа, поэтому вы проверяете, действительно ли это (if (gresult)
), и передаете его следующему eval_()
.
Но что происходит при объединении g()
и h()
? И объединение также f()
?
Если я правильно понимаю, h()
выполняется раньше и возвращает int
; поэтому gresult
- это int
.
Когда вы проверяете
if (gresult)
, вы не проверяете, действительно ли gresult
, но если gresult
равен нулю или нет.
Но это работает (я имею в виду ... компилировать), и целочисленное значение используется для вызова g()
, который ждет int const
.
Но когда результат g()
auto gresult = other(*(args)...);
(то есть std::optional<int>
) используется для вызова f()
(который ждет int
), у вас это
if (gresult)
правильно проверьте, gresult
действительно, но когда вы звоните f()
return this->eval_(gresult);
, вы переходите к f()
a std::optional<int>()
, а не к int
.
Не уверен в решении ( не уверен, что именно вы хотите, и насчет руководств по вычету std::option
), но мне кажется, что вы должны наложить, что gresult
- это std::option
какого-то типа
std::option gresult{ other( args.value()... ) };
, поэтому следующая проверка
if ( gresult )
всегда имеет значение gresult
, затем вы должны передать значение из gresult
следующей функции
return this->eval_( gresult.value() );
Обратите внимание, что в следующем коде
int a;
std::optional b{a};
std::optional c{b};
static_assert( std::is_same_v<decltype(b), std::optional<int>> );
static_assert( std::is_same_v<decltype(c), std::optional<int>> );
и b
, и c
равны std::optional<int>
Я имею в виду ... используя инструкции по выводу для std::optional
, если аргумент - std::optional
, результирующий тип будет таким же.
Я полагаю что это должно сработать для вас, но я не уверен, что именно вы хотите.