Pattern-match/SFINAE 关于特定 类 的容器参数化?

Pattern-match/SFINAE on parameterization of container for specific classes?

我有 Base class 和一些 Derived class。来自外部代码的某些位模式可以制作这些,并且有构建它们的通用代码。该通用代码必须使用显式模板 "factory":

auto d = factory<D>(data); // where D is some Derived class

此工厂为 class 派生自 Base 的 ES 启用了 SFINAE:

template<
    class T,
    typename = typename std::enable_if<
        std::is_base_of<Base, T>::value
    >::type
>
T factory(ExternalData &data) {
    T result;
    if (!result.initFromData(&data))
        throw std::runtime_error("data is not set");
    return result;
}

我想添加另一个适用于 std::experimental::optional<Derived> 的变体,用于位模式指示未设置的情况。在这种情况下,通用代码将传入以下任一类型:

auto dod = factory<DOD>(data); // DOD can be Derived or std::optional<Derived>

使用这样的显式参数化,我将如何创建另一个 SFINAE 变体,它 "pattern match" 只存在于 std::experimental::optional<any class whose base is Base>?

如果我能写的话,我的愿望是:

template<
    std::experimental::optional<class T>, // imaginary
    typename = typename std::enable_if<
        std::is_base_of<Base, T>::value
    >::type
>
std::optional<T> factory(ExternalData &data) {
    T result;
    if (!result.initFromData(&data))
        return nullopt;
    return result;
}

是否有实现愿望的非虚构版本?我查看了 "using SFINAE for template class specialisation"(和其他几个),似乎有一些方法可以合作破解一些东西,如果我写的话,用一个容器来完成它(?),但我是否错过了一个简单的答案?

#include <type_traits>

template <typename T>
struct extract_optional;

template <typename T>
struct extract_optional<std::experimental::optional<T>>
{
    using type = T;
};

template <typename T>
using extract_optional_t = typename extract_optional<T>::type;

template <
    typename T,
    typename OP = extract_optional_t<T>,
    typename = typename std::enable_if<
        std::is_base_of<Base, OP>::value
    >::type
>
std::experimental::optional<OP> factory(ExternalData &data) {
    OP result;
    if (!result.initFromData(&data))
        return nullopt;
    return result;
}

DEMO