模式匹配/SFINAE关于特定类的容器参数化

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

本文关键字:参数 SFINAE 于特定 模式匹配      更新时间:2023-10-16

我有Base类和一些Derived类。来自外部代码的某些位模式可以实现这些,并且有通用代码来构建它们。通用代码必须使用一个明确的模板"工厂":

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

该工厂为从Base:派生的类启用了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变体,该变体将"模式匹配"为仅适用于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;
}

有没有一种非想象的实现欲望的方式?我研究了"使用SFINAE进行模板类专业化"(以及其他一些(,如果我写了一些东西(?(,似乎有一些方法可以合作破解一些东西,用容器来完成它,但我错过了一个简单的答案吗?

#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